Когда антивирусные компании впервые начали публиковать обзоры Flame, с определенного угла зрения они читались как самая настоящая реклама этого продвинутого зловреда. Слаженный коллектив, миллионы долларов «инвестиций», высокие технологии, архитектура, паттерны, высочайшая квалификация… Вкусно звучит, не правда ли? Разумеется, абсолютное большинство продвинутой малвари пишется под винду, но это не значит, что мы, мобильные кодеры, не можем кое-чему у них подучиться! Может быть, и про нас когда-нибудь напишут хвалебные обзоры? 🙂

WARNING


Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
 

Немного об Advanced Persistent Threat

C недавних пор в IT-словаре появился новый термин APT — сокращение от английского Advanced Persistent Threat, буквально это можно перевести как «продвинутая постоянная угроза». Под этой аббревиатурой обычно имеют в виду создание и внедрение вредоносных программ, нацеленных на хищение документов и другой важной информации (не всегда APT подразумевает под собой использование малвари, главное здесь — целевая, персонализированная атака, направленная на конкретную компанию и режиссированная человеком в обход систем защиты. — Прим. ред.). Такая малварь встает в систему и незаметно отсылает на сервер все интересное, что есть на компьютере, при этом никак не нарушая привычного ритма работы пользователя. Особо удачливые APT остаются незамеченными несколько лет.

APT-вредоносы отличаются продуманностью и балансом, отчеты о таких бот-сетях содержат много полезной информации: логическая схема организации сети, методы проникновения, логика работы и многое другое.

APT-сети существуют на удивление долго. Так, согласно данным исследователей, сеть Naikon действует с 2009 года. Одна из причин — слабая антивирусная защита.

 

Архитектура

Начнем с логики всего приложения. Хорошая малварь должна обладать гибким кодом — это позволит ей быть долгосрочным проектом. Будет проще обновлять модули, работать командой или просто рефакторить классы с целью сокрытия от сигнатурного поиска антивирусов.

Создавать поддерживаемый Java-код невозможно без паттернов. По сути, паттерны — это общеизвестные шаблоны кода, позволяющие впоследствии легко менять логику приложения. Мы уже разбирали DI-паттерн в статье «Шесть лучших библиотек разработчика», теперь мы реализуем паттерн MVP.

MVP расшифровывается как «Model — View — Presenter». Это три слоя, на которые будет разделено приложение. Паттерны лучше всего изучать на практике, сейчас мы начнем реализовывать интерфейсы, и ты поймешь, что к чему.

Слой View обычно представляет собой пользовательский интерфейс — визуальные объекты приложения, с которыми может взаимодействовать пользователь. В нашем случае это будет объект, отвечающий за сбор файлов на системе:

public interface ViewElement { File getFile(); }

Интерфейс слоя Model используется для обработки и предоставления данных. В классическом сценарии на класс этого интерфейса возлагается вся работа с данными, требуемыми для слоя View; мы будем через Model осуществлять сетевые операции:

public interface ModelCommunication {
  boolean isInternetAvail(Context ctx);
  void sendData(String filename, Integer partOffset, byte[] filePart);
}

Слой Presenter нужен для связи между Model и View, а также для передачи команд из пользовательского интерфейса. Именно благодаря Presenter слои Model и View возможно разрабатывать без оглядки друг на друга, а в главном Activity приложения будет минимум кода:

public interface Presenter { void sendFile(Context ctx); }
 

Больше паттернов!

Как ты уже знаешь из наших статей, в Android все сетевые запросы выполняются в отдельном потоке. Так как время таких запросов нелинейно, нужно будет как-то оповещать Presenter о результатах отправки данных. Можно останавливать работу Presenter циклом с использованием команды sleep, но это плохой подход, и лучше так не делать.

В Android есть готовая Java-реализация паттерна «Наблюдатель» (Observer). Этот шаблон позволяет в приложении быстро реализовать связь «один ко многим»: при изменении состоянии одного объекта остальные будут автоматически оповещены об этом. Объект, который находится под наблюдением, называется Observable и наследует одноименный класс. Объекты-наблюдатели наследуют класс Observer.

Как ты видишь, создание приложения, на 100% следующего одному шаблону, — скорее утопия. Сегодня мы используем два паттерна, причем один из них серьезно модифицирован.

Рис. 1. Схема приложения
Рис. 1. Схема приложения
 

Реализация

Теперь можно создать классы, реализующие интерфейсы выбранных паттернов. За поиск файлов на устройстве будет отвечать класс FileFunc. Нам сейчас не так важно, как именно он будет найден на устройстве, главное — реализовать метод, предоставляющий доступ файлу для отправки:

public class FileFunc implements ViewElement {
  @Override
  public File getFile() { ...return mFile; }
}

Вопрос поиска файлов на устройстве мы уже поднимали не раз. К примеру, ты можешь почитать об этом в статье «Шифровальщик для Android».

private void dirScan(File dir){
  if( dir.isFile()) {
    Log.e("file", " "+dir.toString());
  } else if( dir.isDirectory() ) {
    for( File child : dir.listFiles() ) { dirScan(child); }
  }
  ...
}

За сетевую часть будет отвечать класс NetworkFunc. Он будет расширять Observable, это позволит ему рассылать информацию о статусе отправленных в сеть пакетов:

public class NetworkFunc extends Observable implements ModelCommunication { ... }

Класс PresentFunc свяжет сетевую и файловую часть приложения. В главном Activity приложения работа с ним сведется только к вызову метода sendFile. Поскольку данный класс не может работать самостоятельно, в конструкторе должны быть указаны необходимые переменные. Тут же подпишемся на обновления, которые будут происходить в сетевом модуле:

public class PresentFunc implements Presenter, Observer {
  ...
  PresentFunc( FileFunc mFile, NetworkFunc networkFunc) {
    this.fileFunc =mFile;
    this.networkFunc=networkFunc;
    networkFunc.addObserver(this);
  }
}
 

На старт!

Теперь подумаем, как запускать процессы поиска и отправки данных. Для этого подойдет класс Service, позволяющий делать практически любые операции в фоне и незаметно для пользователя. Запустить его поможет класс AlarmManager, более подробно об использовании которого ты можешь почитать в статье моего коллеги «Хакерский cron для Android» — очень рекомендую к прочтению.

AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent serviceIntent = new Intent(this,MainService.class);
PendingIntent pIntent = PendingIntent.getService(this,0,serviceIntent,0);
 

Создаем объекты

Как ты, наверное, уже понял, все объекты будут инициализированы в MainService:

Продолжение статьи доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все статьи на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта, включая эту статью. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи одну статью

Заинтересовала статья, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для статей, опубликованных более двух месяцев назад.


1 комментарий

Подпишитесь на ][, чтобы участвовать в обсуждении

Обсуждение этой статьи доступно только нашим подписчикам. Вы можете войти в свой аккаунт или зарегистрироваться и оплатить подписку, чтобы свободно участвовать в обсуждении.

Check Also

WWW: TLDR pages — замена справке man, показывающая только самое важное

Что ты делаешь каждый раз, когда набираешь команду man в Linux или Unix? Правильно: тяжело…