История о маленьком троянце, который смог
Главная опасность приложений, втайне от пользователя получающих root-доступ на мобильном устройстве, заключается в том, что они могут предоставлять доступ к зараженному устройству куда более продвинутым и опасным зловредам с хорошо продуманной архитектурой. Мы опасались, что троянцы, несанкционированно получающие права суперпользователя и использующие их для установки легитимных приложений и показа рекламы, начнут устанавливать вредоносные программы. Наши опасения оправдались: с помощью таких рутовальщиков стал распространяться самый сложный из известных нам мобильных троянцев.
Рутовальщики
В нашей предыдущей статье мы рассказывали о набирающих популярность Android-зловредах, которые несанкционированно получают привилегированный доступ к устройству и используют его для установки приложений и показа агрессивных рекламных сообщений. Часто через некоторое время после попадания подобного зловреда на устройство пользоваться им становится весьма затруднительно – из-за обилия назойливой рекламы и установленных приложений.
Со времени написания первой статьи (август 2015) все изменилось в худшую сторону – число семейств таких вредоносных программ выросло с 4 до 11, распространяются они еще активнее, и намного успешнее осуществляют «рутование». По нашим оценкам, троянцами, получающими права суперпользователя, во второй половине 2015 года были атакованы около 10% пользователей мобильных устройств на платформе Android. Были зарегистрированы случаи, когда такие программы были предустановлены на новых мобильных устройствах из Китая.
Впрочем, стоит отметить, что устройства с ОС Android выше версии 4.4.4 имеют куда меньше уязвимостей, с помощью которых можно получить root-доступ. Поэтому в основном целью подобных зловредов являются ОС предыдущих версий, которые все еще установлены на большинстве устройств пользователей. Диаграмма, приведенная ниже, показывает распределение пользователей нашего продукта в зависимости от версии ОС Android. Как видно на диаграмме, около 60% пользователей пользуются устройствами, на которых упомянутые троянцы могли бы заполучить привилегии суперпользователя.
Версии операционной системы Android, используемые пользователями наших продуктов
Отметим, что хозяева описанных ранее троянцев, таких как Leech, Ztorg, Gorpo (а также зловредов нового семейства Trojan.AndroidOS.Iop), действуют сообща. Зараженные такими зловредами устройства обычно образуют своеобразный «рекламный ботнет», через который рекламные троянцы распространяют друг друга и рекламируемые приложения. Уже через несколько минут после установки одного из таких троянцев на атакованном устройстве работают все остальные активные зловреды, входящие в эту «сеть». Злоумышленники наживаются на рекламе и установках легитимных приложений.
В 2015 году с помощью такого «рекламного ботнета» начали распространяться зловреды, несущие непосредственную угрозу пользователю. В том числе так распространяется один из самых сложных мобильных троянцев из всех, что попадали к нам на анализ.
Уникальный троянец
С помощью «рекламного ботнета» распространяется уникальный в своем роде троянец, который имеет следующие особенности:
- Модульная функциональность вкупе с активным использованием привилегий суперпользователя.
- Основная часть функциональности зловреда существует только в оперативной памяти устройства.
- Троянец модифицирует в памяти системный процесс Zygote для получения персистентности.
- При создании зловреда были использованы промышленные подходы к разработке ПО, из чего следует, что его авторы обладают высокой квалификацией.
Троянец устанавливается в папку, содержащую системные приложения, под именами, которые и в самом деле могли бы быть у системных приложений (например, AndroidGuardianship.apk, GoogleServerInfo.apk, USBUsageInfo.apk и т.д.).
В начале своей работы зловред собирает следующую информацию:
- Имя устройства
- Версия операционной системы
- Размер SD карты
- Информация об оперативной памяти устройства (из файла «/proc/mem»)
- IMEI
- IMSI
- Список установленных приложений
Собранная информация отправляется на сервер злоумышленников, адрес которого троянец получает из списка, прописанного в коде:
- bridgeph1.zgxuanhao.com:8088
- bridgeph1.zgxuanhao.com:8088
- bridgeph2.zgxuanhao.com:8088
- bridgeph3.zgxuanhao.com:8088
- bridgeph4.zgxuanhao.com:8088
- bridgeph1.viewvogue.com:8088
- bridgeph2.viewvogue.com:8088
- bridgeph3.viewvogue.com:8088
- bridgeph4.viewvogue.com:8088
Или, в случае недоступности указанных выше серверов, из списка резервных командных серверов, также прописанного в коде:
- bridgecr1.tailebaby.com:8088
- bridgecr2.tailebaby.com:8088
- bridgecr3.tailebaby.com:8088
- bridgecr4.tailebaby.com:8088
- bridgecr1.hanltlaw.com:8088
- bridgecr2.hanltlaw.com:8088
- bridgecr3.hanltlaw.com:8088
- bridgecr4.hanltlaw.com:8088
В ответ приходит зашифрованный конфигурационный файл, который сохраняется как «/system/app/com.sms.server.socialgraphop.db». Конфигурация регулярно обновляется и состоит из следующих полей:
- mSericode – идентификатор зловреда;
- mDevicekey – идентификатор устройства, генерируемый на сервере (сохраняется в «/system/app/OPBKEY_< mDevicekey >»);
- mServerdevicekey – идентификатор текущего сервера;
- mCD – информация, используемая киберпреступниками для корректировки поведения модулей;
- mHeartbeat – интервал исполнения интерфейса «heartbeatRequest»;
- mInterval – интервал обращения к командному серверу;
- mStartInterval – время, по истечении которого запускаются подгруженные DEX файлы (модули);
- mServerDomains – список основных доменов;
- mCrashDomains – список резервных доменов;
- mModuleUpdate – ссылки, необходимые для загрузки DEX файлов (модулей).
Если поле mModuleUpdate заполнено, то происходит скачивание и сохранение DEX файлов. Затем с помощью DexClassLoader.loadClass() происходит загрузка скачанных файлов в контекст зловреда. После загрузки модули удаляются с диска, т.е. они остаются только в оперативной памяти устройства, что серьезно затрудняет их обнаружение и удаление антивирусными программами.
Загруженные модули для корректного исполнения должны иметь следующие интерфейсные методы:
- init(Context context) – используется для инициализации модулей;
- exit(Context context) – используется для завершения работы модулей;
- boardcastOnReceive(Context context, Intent intent) – используется для перенаправления широковещательных сообщений в модуль;
- heartbeatRequest(Context context) – инициация обращения модуля к командному серверу. Необходима для получения данных модуля, требуемых серверу;
- heartbeatResponce(Context context, HashMap serverResponse) – передача ответа командного сервера модулю.
В зависимости от версии также может использоваться следующий набор интерфейсов:
- init(Context context) – используется для инициализации модулей;
- exec() – используется для исполнения полезной нагрузки;
- exit(Context context) – используется для завершения работы модулей.
Подобный механизм обеспечивает возможность исполнения приложением-загрузчиком модулей, реализующих различную функциональность, и осуществлять их координацию и синхронизацию.
Описанные приложения и загружаемые ими модули используют файлы » androidbin», «conbb», «configopb», «feedback» и «systemcore», хранящиеся в папке /system/bin, для выполнения в системе различных действий с привилегиями суперпользователя. Разумеется, этих файлов на чистой системе нет.
Учитывая описанную модульную архитектуру и привилегированный доступ к устройству, зловред может сотворить буквально все, что угодно. Возможности подгружаемых модулей ограничиваются только фантазией и навыками вирусописателей. Данные зловреды (приложение-загрузчик и загружаемые им модули) относятся к разным видам троянцев, но все они были занесены в наши антивирусные базы с общим наименованием Triada.
На время анализа приложение-загрузчик (детектируется нами как Backdoor.AndroidOS.Triada) скачивал и активировал следующие модули:
- OPBUpdate_3000/Calendar_1000 – два модуля с дублирующей функциональностью, способные скачивать и устанавливать, а также запускать приложения (детектируется как Trojan-Downloader.AndroidOS.Triada.a).
- Registered_1000 – модуль, способный отправлять SMS по запросу командного сервера Детектируется как Trojan-SMS.AndroidOS.Triada.a.
- Idleinfo_1000 – модуль, атакующий приложения, использующие SMS-сообщения для совершения In-App покупок (перехват исходящих текстовых сообщений). Детектируется как Trojan-Banker.AndroidOS.Triada.a.
Использование процесса Zygote
Отличительной особенностью вредоносного приложения является использование процесса Zygote для внедрения своего кода в контекст всех приложений на устройстве. Процесс Zygote – это родительский процесс для всех Android-приложений, который содержит системные библиотеки и фреймворки, используемые практически всеми приложениями. Этот процесс является шаблоном для каждого нового приложения, и это значит, что как только троянец попадет в этот процесс, он становится частью этого шаблона и будет попадать в каждое запускаемое приложение. Мы впервые сталкиваемся с подобной техникой ITW, до этого использование Zygote реализовывалось только в виде Proof-of-Concepts.
На схеме, представленной ниже, представлена архитектура зловреда.
Рассмотрим подробнее, как происходит заражение процесса Zygote.
Подготовительный этап и тестирование
Вся магия начинается в функции crackZygoteProcess(), которая содержится в модуле Trojan-Banker. Ее код можно увидеть на скриншоте ниже.
Как видно из кода, сначала троянец подгружает библиотеку libconfigpppm.so и вызывает экспортируемую ею функцию configPPP (первая подчеркнутая красным строка на скриншоте). Если эта функция успешно отработала и вызов стандартной функции Android API System.getProperty() с нестандартным параметром «pp.pp.pp» (позже поясним зачем) вернул значение, отличное от null, то троянец запускает исполняемый ELF-файл configpppi, передавая ему на вход PID процесса zygote.
Расскажем, как все происходит, по порядку.
Внутри функции configPPP из libconfigpppm.so троянец первым делом получает адрес (внутри адресного пространства своего процесса), по которому загружен файл, который реализует стандартную функцию Android API ActivityThread.main(). Далее по полученному адресу и при помощи файла / proc/self/maps определяет путь и имя этого файла. В подавляющем большинстве случаев это будет / system/framework/framework.odex. Но данный механизм отработает и в случае, если framework.odex имеет нестандартное имя или путь.
Троянец читает данный файл с диска и сравнивает с тем, что уже подгружен в память процесса. Проверка происходит следующим образом:
- файл разбивается на 16 равных блоков;
- из каждого блока читаются первые 8 байт;
- эти 8-байтовые последовательности сравниваются с аналогичными последовательностями из файла в памяти процесса.
Если проверка на соответствие файла в памяти с прообразом на диске завершилась неудачно, функция configPPP прекращает дальнейшую работу и возвращает соответствующий код ошибки (-103 в данном случае).
Если же проверка прошла успешно, начинается процесс патчинга образа файла framework.odex в памяти процесса троянца.
Все начинается с получения данных класса ActivityThread, определенного в framework.odex, при помощи функций dexFindClass и dexGetClassData. Данные функции авторы троянца заимствовали прямиком из открытых исходных кодов виртуальной машины Dalvik. Далее, используя полученные данные класса, троянец итерирует по списку методов, реализованных в данном классе, пока не дойдет до метода с именем main. И получает байт-код этого метода с помощью функции dexGetCode (также заимствованной из исходных кодов Dalvik), сохраняя указатель на него.
Затем троянец проверяет, не пропатчен ли уже код этого метода, сравнивая его с кодом того же метода, полученного из файла на диске. И если метод уже пропатчен, работа библиотеки завершается.
После этого троянец ищет в таблице строк файла framework.odex в памяти процесса строку нужной длины – от 32 до 62 символов, – записывает на ее место строку » /system/lib/libconfigpppl.so» и сохраняет ее ID (порядковый номер в таблице строк).
Далее ищет в таблице методов файла framework.odex в памяти процесса один из методов с именем loop, attach, setArgV0. Выбирается тот, который попадется первым, или, если данные методы не были найдены, то берется предпоследний метод из таблицы методов. Выбранный метод заменяется на стандартный метод System.load(), и его ID сохраняется. На скриншоте ниже показан псевдокод, отвечающий за эту операцию:
На этом подготовительный этап можно считать законченным, и троянец переходит к самому интересному. Он добавляет в памяти (!sic) к байт-коду оригинального метода main класса ActivityThread еще несколько инструкций. Представленный ниже байт-код помещается перед байт-кодом оригинального метода:
1A 00 [strID, 2 bytes] //const-string v0, «/system/lib/libconfigpppl.so»
71 10 [methID, 2 bytes] 00 00 //invoke-static {v0}, Ljava/lang/System;->load(Ljava/lang/String;)V
0E 00 //return-void
Где strID – сохраненный ID перезаписанной ранее строки, а methID – сохраненный ID перезаписанного ранее метода.
В результате совершенных модификаций при вызове функции ActivityThread.main() в контекст вызвавшего эту функцию процесса будет подгружаться библиотека /system/lib/libconfigpppl.so. Но, так как framework.odex пропатчен только в контексте процесса троянца, то библиотека будет подгружаться только в процесс троянца. Это, на первый взгляд, бессмысленное действие выполняется в целях тестирования возможности зловреда модифицировать процесс Zygote. Если описанные действия не вызвали ошибок в контексте самого приложения, то они не вызовут ошибок и в контексте системного процесса. Злоумышленники подходят с осторожностью к такому сложному действию как изменение адресного пространства Zygote, так как любое неосторожное действие в этом процессе может привести к немедленному падению системы. Именно поэтому осуществляется «тестовый прогон», позволяющий проверить работоспособность описанной методики на устройстве пользователя.
На этом работа библиотеки libconfigpppm.so почти закончена. В заключение, она записывает в файл /data/configppp/cpppimpt.db некоторые сохраненные в результате своей работы данные , которые потом будут использоваться в процессе реальной модификации Zygote. А именно:
- ID перезаписанной строки (4 байта);
- содержимое строки, которая перезаписывается (64 байта);
- ID метода, который перезаписывается (4 байта);
- указатель на структуру Method перезаписываемого метода (4 байта);
- содержимое структуры Method для метода ActivityThread.main() (52 байта);
- адрес файла framework.odex в памяти процесса троянца (4 байта);
- список структур, которые использовались для проверки на соответствие файла в памяти с его прообразом на диске (192 байта):
- указатель на начало очередного блока framework.odex;
- первые 8 байт блока.
- размер файла framework.odex в памяти (до патчинга) (4 байта);
- указатель на структуру DexFile файла framework.odex (4 байта);
- содержимое структуры DexFile файла framework.odex (44 байта);
- указатель на структуру Method функции System.load() (4 байта);
- размер байткода метода ActivityThread.main() до патчинга (4 байта);
- байт-код метода ActivityThread.main() до патчинга (длина переменна);
И, наконец, троянец вызывает метод ActivityThread.main() (который уже пропатчен), подгружая таким образом библиотеку /system/lib/libconfigpppl.so в свой процесс. Посмотрим, что же происходит внутри нее, но сначала заглянем внутрь файла configpppi, который осуществляет реальную модификацию адресного пространства Zygote.
Модификация Zygote
Делает он практически то же самое, что и файл libconfigpppm.so, т. е. патчит функцию ActivityThread.main() внутри framework.odex, подгруженного в процесс. Только на этот раз это действие происходит не внутри процесса троянца, а внутри процесса, PID которого передается в качестве аргумента файлу configpppi, т. е. процесса Zygote. Запись в процесс Zygote происходит при помощи системного вызова ptrace(), позволяющего читать и писать в память другого процесса. И теперь троянец не ищет интересующие его адреса и другие данные для патчинга внутри процесса, а берет их из уже подготовленного ранее файла /data/configppp/cpppimpt.db.
Процесс Zygote – это родительский процесс для всех Android-приложений. Он содержит в себе все необходимые системные библиотеки и фреймворки, которые используются практически всеми приложениями. Этот процесс был придуман, чтобы не загружать целую кучу библиотек в память каждый раз, когда пользователь запускает очередное приложение. При запуске приложения пользователем процесс Zygote просто вызывает системный вызов fork(), который создает дочерний процесс, представляющий собой полную копию родителя, и в дочерний процесс загружаются только непосредственно данные запускаемого приложения. Такой механизм, в частности, позволяет сократить время запуска приложений.
Таким образом, при запуске нового Android-приложения в него из Zygote будет попадать измененная троянцем версия framework.odex (с подгруженной библиотекой libconfigpppl.so). Иными словами, библиотека libconfigpppl.so попадает во все новые приложения и может изменять логику их работы. Это открывает широкий спектр возможностей перед злоумышленниками.
Подмена стандартных функций Android Framework
После того как библиотека /system/lib/libconfigpppl.so оказалась загружена внутри Zygote стандартной функцией System.load(), срабатывает ее функция JNI_OnLoad.
Внутри этой функции троянец первым делом восстанавливает исходные значения перезаписанных строки и метода. Для этого используются данные, сохраненные в файле /data/configppp/cpppimpt.db.
Далее троянец подгружает DEX файл configpppl.jar, используя для этого стандартную функциональность Android API, а именно класс dalvik.system.DexClassLoader.
И, чтобы удостовериться, что DEX файл был успешно подгружен, вызывает его метод pppMain в классе PPPMain, который только выводит в Logcat строку «PPP main started».
Следующий этап – подготовка хуков для различных методов Android Framework (framework.odex). Сначала троянец по очереди проверяет наличие в configpppl.jar всех методов, которые будут использоваться в качестве хуков, с помощью функции checkPackageMethodExits (определена в configpppl.jar). Далее троянец подготавливает хуки для следующих методов:
- java.lang.System.getProperty()
- android.app.Instrumentation.newApplication()
- com.android.internal.telephony.SMSDispatcher.dispatchPdus()
- android.app.ActivityManager.getRunningServices()
- android.app.ActivityManager.getRunningAppProcesses()
- android.app.ApplicationPackageManager.getInstalledPackages()
- android.app.ApplicationPackageManager.getInstalledApplications()
Хуки устанавливаются при помощи вызова стандартной функции RegisterNatives(). Эта функция предназначена для связывания Java-методов с их нативной реализацией (т. е. на языке C/C++). Таким образом троянец подменяет стандартные функции Android Framework (которые перечислены выше) на функции, реализованные в libconfigpppl.so.
Рассмотрим подробнее, зачем троянцу понадобилось подменять эти функции.
Проверка успешности модификации Zygote
Функция, которая подменяет оригинальную getProperty(), сначала проверяет, какой параметр ей передается на вход. И если это строка » pp.pp.pp«, то сразу же возвращает значение true. Иначе вызывает оригинальную функцию getProperty(), передавая ей на вход полученный параметр. С помощью вызова этой функции с параметром » pp.pp.pp» из Java-кода (показан на первом скриншоте в этом разделе) троянец проверяет, удалось ли ему успешно подменить функции Android Framework. Если подмена произошла успешно, то, как и говорилось ранее, троянец запускает исполняемый ELF-файл configpppi, передавая ему на вход PID процесса Zygote.
Далее троянец «убивает» процессы интересующих его в первую очередь приложений: com.android.phone, com.android.settings, com.android.mms – это стандартные приложения «Телефон», «Настройки» и «Сообщения». Эти приложения автоматически запустятся при следующей разблокировке устройства и будут содержать в себе полученный от Zygote измененный framework.odex со всеми хуками, установленными libconfigpppl.so.
Модификация исходящих SMS
Функция, которая подменяет newApplication(), сначала вызовет оригинальную функцию, а потом еще 2 функции configpppl.jar: onModuleCreate() и onModuleInit().
Функция onModuleCreate() проверяет, в контексте какого приложения она запущена. И в зависимости от этого устанавливает значение глобальной переменной mMainAppType:
- если функция работает в контексте приложения com.android.phone, то mMainAppType присваивается значение 1;
- если функция работает в контексте приложения com.android.settings или com.android.mms, то mMainAppType присваивается значение 2;
- если функция работает в контексте одного из приложений: com.android.system.google.server.info, com.android.system.guardianship.info.server, com.android.sys.op, com.android.system.op., com.android.system.kylin., com.android.kylines, com.android.email, com.android.contacts, android.process.media, com.android.launcher, com.android.browser , то mMainAppType присваивается значение -1;
- если функция работает в контексте любого другого приложения, то mMainAppType присваивается значение 0.
Функция onModuleInit() на основе установленного значения mMainAppType выполняет одну из инициализирующих функций:
Таким образом, троянец меняет свою функциональность в зависимости от процесса, в котором запущен. Например, если значение mMainAppType равно -1 (т. е. внутри приложений com.android.email, com.android.contacts и т. д.), то троянец никак себя не проявляет.
Если троянец запущен внутри com.android.phone, то он регистрирует обработчик событий com.ops.sms.core.broadcast.request.status и com.ops.sms.core.broadcast.back.open.gprs.network. Первый из них устанавливает в качестве значения глобальной переменной mLastSmsShieldStatusTime текущее время, а второй включает передачу данных по мобильным сетям.
Если троянец запущен внутри com.android.settings или com.android.mms, то он регистрирует обработчики событий:
- com.ops.sms.core.broadcast.request.status;
- com.ops.sms.core.broadcast.back.open.gprs.network;
- com.ops.sms.core.broadcast.back.send.sms.address.
Первые два из них такие же, как и в предыдущем случае, а третий выполняет отправку SMS на номер и с текстом, указанными в параметрах события.
Если же троянец запущен внутри любого другого приложения (кроме тех, что провоцируют установку значения mMainAppType = -1), то сначала он проверяет, использует ли приложение библиотеку libsmsiap.so:
И в зависимости от результата вызывает одну из функций: PISmsCore.invokeMMMain() или PISmsCore.invokeOtherMain().
Обе эти функции вызывают PISmsCore.initInstance(). Она делает следующее:
-
- инициализирует глобальные переменные троянца различными данными об устройстве пользователя ( IMEI, IMSI и т. п.);
- подменяет системные биндеры (Binder IPC) «isms» и «isms2», используемые приложением, на свои собственные
- создает множество различных директорий в каталоге /sdcard/Android/com/register/, в которые будет в дальнейшем писать свои различные логи;
- регистрирует обработчик событий com.ops.sms.core.broadcast.responce.shield.status и com.ops.sms.core.broadcast.responce.sms.send.status, который просто записывает время наступления этих событий в соответствующие переменные;
- если функция была вызвана из PISmsCore.invokeMMMain(), то создает новый поток, в котором в бесконечном цикле включает передачу данных по мобильным сетям, таким образом не давая пользователю ее выключить.
Самое интересное из всех этих действий – это подмена системных биндеров «isms» и «isms2».
Биндеры (Binder IPC) – это механизм межпроцессного взаимодействия на ОС Android. В случае использования биндеров весь обмен данными между различными приложениями происходит через специальное псевдо-устройство – / dev/binder. Фактически же, для передачи данных используется адресное пространство памяти ядра ОС. Схема подобного взаимодействия изображена ниже.
Например, когда приложение хочет отправить SMS-сообщение, оно вызывает стандартную функцию Andoroid API – sendTextMessage (или sendMultipartTextMessage). Это приводит к вызову метода transact() системного биндера «isms» (или «isms2»), который в итоге передаст эти данные GSM-модулю телефона.
Метод transact() переопределен в реализации биндера «isms», который подменяет оригинальный. Таким образом, когда приложение отправляет SMS-сообщение, оно (сообщение) попадает под контроль троянца, проходя через вредоносный биндер.
В методе transact() троянец достает из проходящего через него SMS-сообщения номер получателя, текст сообщения и номер центра SMS-сообщений и отправляет их на один из своих C&C серверов (выбирается случайным образом):
- bridgeph1.zgxuanhao.com:8088
- bridgeph2.zgxuanhao.com:8088
- bridgeph3.zgxuanhao.com:8088
- bridgeph4.zgxuanhao.com:8088
- bridgeph1.viewvogue.com:8088
- bridgeph2.viewvogue.com:8088
- bridgeph3.viewvogue.com:8088
- bridgeph4.viewvogue.com:8088
Ответ C&C сервера, помимо прочих данных, может содержать новый номер получателя SMS-сообщения и новый текст отправляемого сообщения.
Если же интернет в момент перехвата SMS-сообщения недоступен, то троянец попытается получить новый номер получателя SMS и текст сообщения из локальных файлов конфигурации, которые он хранит в / sdcard/Android/com/register/localuseinfo/.
В итоге троянец подменяет текст сообщения и номер его получателя и пытается отправить SMS тремя различными способами одновременно:
- Используя стандартную функцию Android API – sendTextMessage. Это приведет к вызову все того же метода transact(), подмененного троянцем » isms» биндера;
- Используя отправку события «com.ops.sms.core.broadcast.back.send.sms.address». Оно будет получено и обработано тем же модулем троянца, но внутри приложений «Сообщения» или «Настройки»;
- Используя передачу номера нового получателя SMS и текста сообщения оригинальному системному биндеру «isms».
Когда троянец отправляет SMS-сообщение одним из этих способов, он сохраняет новый текст сообщения и номер получателя в специальной переменной. И перед отправкой очередного SMS-сообщения он проверяет, не было ли оно уже отправлено. Это позволяет предотвратить бесконечные рекурсивные вызовы метода transact(), таким образом каждое отправляемое SMS-сообщение будет перенаправлено подмененным биндером только один раз.
Помимо функции PISmsCore.initInstance(), функция PISmsCore.invokeMMMain() вызывает еще одну функцию – PIMMCrack.initInstance(). Здесь троянец пытается определить версию mm.sms.purchasesdk, используемую приложением, внутри которого он работает. mm.sms.purchasesdk – это SDK китайского происхождения, которое внедряется разработчиками в их приложения для реализации функциональности покупок внутри своих приложений посредством SMS-сообщений. Троянец знает, что приложение использует данное SDK, так как предварительно он проверил, использует ли оно библиотеку libsmsiap.so, которая также является частью этого SDK.
Таким образом, механизм, описанный в этой главе, позволяет троянцу модифицировать исходящие SMS-сообщения, отправляемые другими приложениями. Мы полагаем, что злоумышленники используют эту технику для незаметного воровства финансовых средств пользователей. Например, когда пользователь покупает что-то во внутриигровом магазине какой-нибудь игры для Android (если эта игра использует SDK для оплаты внутриигровых покупок через SMS — например, mm.sms.purchasesdk), злоумышленники могут модифицировать исходящее платежное SMS-сообщение таким образом, чтобы получить деньги пользователя вместо разработчиков игры. В результате пользователь, скорее всего, не заподозрит, что его деньги были украдены злоумышленниками. Но поскольку оплаченный контент он так и не получит, то, вероятно, подумает, что это баг в игре. Еще один вариант – деньги уходят злоумышленникам, но пользователь контент получает. В таком случае троянец совершает хищение финансовых средств не столько пользователя, сколько разработчиков легитимного ПО.
Фильтрация входящих SMS
Оригинальная функция dispatchPdus(), как показано на схеме ниже, используется для рассылки PDU-данных (Protocol Data Unit, низкоуровневая сущность представления данных, используется во многих коммуникационных протоколах) входящих SMS-сообщений всем установленным приложениям. Далее все приложения, подписанные на это событие, могут получать и обрабатывать входящие SMS-сообщения, которые приходят в виде PDU-данных вместе с широковещательным событием.
Функция, которая подменяет оригинальную dispatchPdus(), вызывает функцию moduleDispatchPdus() из configpppl.jar. Эта функция сначала проверяет, в контексте какого приложения она запущена, и, если это не com.android.phone (т. е. стандартное приложение «телефон»), то просто формирует и отправляет всем приложениям событие android.provider.Telephony.SMS_RECEIVED (вместе в пришедшими PDU) – стандартное событие, означающее получение входящего SMS-сообщения, на которое подписано, например, стандартное приложение для работы с SMS («Сообщения» или Hangouts).
Если же функция запущена в контексте приложения com.android.phone, то троянец проверяет, с какого номера и с каким текстом получено SMS-сообщение. Для проверок используются несколько файлов, которые находятся в директориях: / sdcard/Android/com/register/infowaitreceive/ и /sdcard/Android/com/register/historyInfo/. Имена файлов в этих директориях имеют постфикс, содержащий дату и время последнего обновления. И если файлы были обновлены раньше, чем происходило последнее обращение к C&C серверу, то они просто удаляются и никаких проверок пришедшей SMS дальше не происходит. Иначе, все файлы, найденные в указанных директориях, расшифровываются, и из них достаются и заносятся в список номера и ключевые слова (для поиска в тексте SMS-сообщения).
Если SMS-сообщение пришло с номера из списка или его текст содержит одно (или несколько) из ключевых слов, то троянец отправляет его вместе с событием android.provider.Telephony.SMS_RECEIVEDcom.android.sms.core, которое получат только те, кто подписан на него. На «чистом» Android устройстве нет ни одного такого приложения. Иначе, отправляет его вместе со стандартным событием android.provider.Telephony.SMS_RECEIVED. Таким образом некоторые входящие SMS-сообщения могут быть отфильтрованы, и ни пользователь, ни какое-либо установленное приложение в системе его не увидят.
Сокрытие модулей троянца из списка запущенных сервисов
Данная функция используется для получения списка запущенных сервисов. Подменяя эту функцию, троянец скрывает свои модули из этого списка. А именно исключает из списка, возвращаемого оригинальной функцией getRunningServices(), следующие элементы:
- com.android.system.google.server.info
- com.android.system.guardianship.info.server
- com.android.sys.op
- com.android.system.op.
- com.android.system.kylin.
- com.android.kylines.
Сокрытие модулей троянца из списка запущенных приложений
Данная функция используется для получения списка запущенных приложений. Подменяя эту функцию, троянец скрывает свои модули из этого списка. А именно исключает из списка, возвращаемого оригинальной функцией getRunningAppProcesses(), следующие элементы:
- com.android.system.google.server.info
- com.android.system.guardianship.info.server
- com.android.sys.op
- com.android.system.op.
- com.android.system.kylin.
- com.android.kylines.
Сокрытие модулей троянца из списка установленных пакетов
Данная функция используется для получения списка установленных пакетов. Подменяя эту функцию, троянец скрывает свои модули из этого списка. А именно исключает из списка, возвращаемого оригинальной функцией getInstalledPackages(), следующие элементы:
- com.android.system.google.server.info
- com.android.system.guardianship.info.server
- com.android.sys.op
- com.android.system.op.
- com.android.system.kylin.
- com.android.kylines.
Сокрытие модулей троянца из списка установленных приложений
Данная функция используется для получения списка установленных пакетов приложений. Подменяя эту функцию, троянец скрывает свои модули из этого списка. А именно исключает из списка, возвращаемого оригинальной функцией getInstalledApplications(), следующие элементы:
- com.android.system.google.server.info
- com.android.system.guardianship.info.server
- com.android.sys.op
- com.android.system.op.
- com.android.system.kylin.
- com.android.kylines.
Заключение
Приложения, втайне от пользователя получающие root-доступ на мобильном устройстве, предоставляют доступ к зараженному устройству более сложным и опасным зловредам – в частности, мобильному троянцу Triada, самому сложному из известных нам. После попадания на устройство пользователя Triada внедряется практически во все запущенные процессы и продолжает существовать только в оперативной памяти. Кроме того, все отдельно запущенные процессы троянца скрываются от пользователя и других приложений. В итоге обнаружение и удаление троянца становится крайне затруднительным как для пользователя, так и для защитных решений антивирусных компаний.
Основная функциональность троянца направлена на перенаправление финансовых SMS-транзакций, осуществляемых в ходе оплаты пользователем различного дополнительного контента в легитимных приложениях. После оплаты деньги пользователя попадают не к разработчику ПО, а к злоумышленникам. В зависимости от того, получает ли пользователь оплаченный контент, троянец совершает хищение финансовых средств либо у пользователя (если контент пользователем не получен), либо у разработчиков легитимного ПО (если контент пользователем получен).
Очевидно, что троянец Triada разработан киберпреступниками, которые очень хорошо разбираются в атакуемой мобильной платформе. Спектр техник, использованных данным троянцем, не встречается ни в одном из известных нам мобильных зловредов. Использованные методы сокрытия и получения персистентности позволяют эффективно избегать обнаружения и удаления всех компонетов зловреда после их установки на зараженном устройстве, а модульная архитектура позволяет злоумышленникам расширять и менять функциональность, и ограничивают их только возможности операционной системы и установленные на устройстве приложения. Так как зловред проникает во все приложения, установленные на системе, киберпреступники потенциально могут модифицировать их логику, чтобы реализовать новые векторы атаки на пользователей и максимизировать свою прибыль.
По сложности Triada не уступает Windows-зловредам, что знаменует своеобразный Рубикон в эволюции угроз, направленных на платформу Android. Если раньше большинство троянцев под эту платформу были довольно примитивными, то теперь «на сцену» выходят новые угрозы – с высоким уровнем технической сложности.
Атака на Zygote: новый виток эволюции мобильных угроз
Азик
Спасибо за информацию! Но скажите — как защититься от этого вируса?
using.System.Net
Полюбому не обошлось без кодеров из google
Мария
Товарищи авторы, а как пользователю бороться с этим трояном? Это реально сделать самостоятельно или нужно нести в сервис, или стоит вообще выкинуть телефон?
Илья
Нас везде обманывают и обворовывают 🙂 — просто жить с этим дальше и все. В сервисах точно не помогут 😛
Vasya
Это было неизбежно.
Den-Dzen-Pen
Азик, Мария.
В первую очередь, НИКОГДА не устанавливать стороннее ПО, не скаченное с маркета.
А если по хорошему, то всегда проверяйте какое разрешение требует приложение. Если это игра, то оно может использовать мультимедиа, но если эта игра требует доступ к телефону и т.п. то сразу шлите куда подальше.
Если же это приложение архиватор, то оно скорее всего требует доступ к файловой системе, но если оно начнет требовать доступ к смс и телефону, то тоже по аналогии, шлите далеко и надолго.
mymedia
Не понятно, как зловред получает права суперпользователя. Ведь просто так ему система не даст оттрассировать и убить чужой процесс.
Umnik
> Со времени написания первой статьи (август 2015)
Здесь остро не хватает ссылки на статью: https://securelist.ru/blog/issledovaniya/26769/puskaem-korni/
E.K.
Добавили.
Alex
При запуске системы этот троян должен тоже как-то запускаться. Если слить прошивку через CWM разобрать и вытереть его, то он не сможет запуститься. Вот только здесь ни слова не сказано где он лежит физически? И как прописан в автозапуск?
Макс
Этот троян находиться в оперативной памяти
Ник2
Так в итоге как удалить этот вирус? Есть способ?
John Connor
Бороться — шить заводской образ прошивки и не ставить ничего на телефон лишнего, тем более не делать рут. А то все добрались до рута, а как себя обезопасить — не знаем.