CERT Polska в апреле 2026 года выложила разбор cifrat - трёхстадийного Android-дроппера, где внешний APK грузил нативную библиотеку, та расшифровывала второй APK под маской Google Play Services, а из него вылезал финальный RAT-модуль с WebSocket C2, стримом экрана и SOCKS5-туннелем. Параллельно CyFirma описала TaxiSpy - банковский троян с RAT-функциональностью, прятавший C2-адреса и Firebase-credentials внутри нативного слоя через rolling XOR. Обе малвари эксплуатируют одну архитектурную идею: доставить вредоносный payload за фасадом легитимного компонента. SilentSDK - условное имя для композитного образца, собранного из задокументированных техник этих семейств. Здесь мы шаг за шагом пройдём весь цикл reverse engineering мобильного SDK с вредоносным RAT: от манифеста до расшифровки C2-адресов из
.rodata нативной библиотеки и перехвата WebSocket-трафика через Frida.Место в цепочке атаки: supply chain через троянизированный SDK
Атака через Compromise Software Supply Chain (T1195.002, Initial Access) - один из самых скрытных векторов доставки мобильного вредоноса. Вместо прямого фишинга или сайдлоада злоумышленник компрометирует звено в цепочке разработки: SDK аналитики, рекламный модуль, библиотеку push-уведомлений. Разработчик приложения подключает троянизированный SDK как рядовую зависимость - и тысячи пользователей получают RAT вместе с легитимным обновлением.Полная цепочка для SilentSDK-подобного сценария:
- Initial Access - разработчик подключает SDK из скомпрометированного источника (T1195.002)
- Execution - при инициализации SDK вызывает
System.loadLibrary(), нативная библиотека расшифровывает embedded payload - Defense Evasion - второй этап маскируется под системный компонент: Google Play Services, analytics framework (T1036.005); зашифрованный payload в нативной библиотеке скрывает вредоносный код от статического анализа (T1027.009)
- Collection - финальный RAT собирает SMS, контакты, нажатия клавиш (T1056.001), скриншоты (T1113), файлы устройства (T1005)
- Command and Control - управление по WebSocket через двунаправленный канал (T1219)
- Exfiltration - данные уходят по тому же C2-каналу (T1041)
booking.interaction.lat/starting/. TaxiSpy, по данным CyFirma, пошёл дальше - заменил категорию LAUNCHER на INFO в манифесте, полностью скрыв иконку из меню приложений. Пользователь не мог найти и удалить приложение стандартными средствами.Контекст применения: этот анализ актуален для internal threat intelligence, аудита мобильных приложений перед интеграцией в корпоративную среду (MDM/MAM), разбора сэмплов при incident response. Для внешнего пентеста mobile-приложений техники помогают понять, какие индикаторы искать при проверке supply chain третьих сторон.
Требования к окружению для анализа мобильного вредоносного ПО
Прежде чем вскрывать сэмпл - зафиксируем инструментальный стек.Системные требования: Linux или macOS, минимум 8 ГБ RAM (16 ГБ если планируете гонять эмулятор и radare2/Ghidra параллельно), Python 3.10+, Java JDK 11+.
| Инструмент | Версия | Назначение | Статус |
|---|---|---|---|
| jadx / jadx-gui | 1.5+ | Декомпиляция DEX в Java | Активный проект |
| apktool | 2.9+ | Распаковка/сборка APK, smali | Активный проект |
| radare2 | 6.1.5 | Анализ нативных .so библиотек | Активный проект |
| Frida | актуальная из pip | Runtime хуки, перехват JNI-вызовов | Активный проект |
| objection | актуальная из pip | Обход SSL pinning, exploration | Активный проект |
| MobSF | 4.x | Автоматический статический/динамический скан | Активный проект |
| Burp Suite | Community или Pro | Перехват HTTP/WebSocket-трафика | Коммерческий |
Ещё понадобится Android-эмулятор с root-доступом (Android Studio AVD с образом Google APIs - не Google Play - или Genymotion) либо рутованный физический девайс. Для анализа ARM-библиотек на x86-хосте radare2 работает без дополнительных зависимостей - дизассемблер встроен.
Установка:
pip install frida-tools objection для Frida-стека, brew install jadx apktool (macOS) или сборка из репозиториев для Linux.Статический анализ APK: распознаём вредоносную библиотеку Android
Манифест как первый индикатор
Распаковка APK командойapktool d sample.apk даёт полную структуру приложения с читаемым AndroidManifest.xml. Для SilentSDK-образца ожидаемая картина напоминает то, что CERT Polska обнаружила в манифесте cifrat: избыточные разрешения и компоненты, не свойственные заявленной функциональности.
XML:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<queries><package android:name="io.silent.utility"/></queries>
<receiver android:exported="true" android:name=".core.PackageEventReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
</intent-filter>
</receiver>
REQUEST_INSTALL_PACKAGES - SDK заявляет право ставить другие APK на устройство. Для модуля аналитики или push-уведомлений это бред. QUERY_ALL_PACKAGES даёт видимость всех установленных приложений - именно так TaxiSpy, по данным CyFirma, составлял список банковских приложений на устройстве жертвы. Блок <queries> с явной ссылкой на пакет io.silent.utility - прямое указание на архитектуру дроппера: приложение ожидает появления второго пакета. В cifrat аналогичная конструкция ссылалась на io.cifnzm.utility67pu. Ресивер на PACKAGE_ADDED отслеживает момент успешной установки дропнутого payload и запускает следующую стадию.Дополнительные красные флаги, зафиксированные в обоих сэмплах:
BIND_ACCESSIBILITY_SERVICE- доступ к Accessibility API, через который RAT выполняет удалённые жесты и перехватывает экранный контентREAD_SMS,READ_CONTACTS,READ_CALL_LOG- прямой сбор данныхMANAGE_EXTERNAL_STORAGE,PACKAGE_USAGE_STATS- расширенный доступ к файловой системе и статистике использованияREQUEST_IGNORE_BATTERY_OPTIMIZATIONS- защита от system kill для фонового процесса RAT
REQUEST_INSTALL_PACKAGES, это уже подозрительно.Декомпиляция: jadx и поиск RAT-логики в SDK
Открываем APK в jadx-gui:jadx-gui sample.apk. Первая точка входа - кастомный Application-класс, указанный в манифесте через android:name. В cifrat это был v0a0cac5c.l0a0cac5c - имя сгенерировано обфускатором. В SilentSDK-сценарии ожидаем аналогичную картину.В
Application.onCreate() или в статическом инициализаторе ищем вызовы System.loadLibrary(). По данным CyFirma, TaxiSpy загружал sysruntime.so - нативную библиотеку, содержащую всю ключевую конфигурацию: bot ID, C2-адреса, Firebase-credentials. В нашем сценарии SDK грузит libsilentcore.so.Дальше систематически проверяем декомпилированный код на:
- Динамическую загрузку DEX: вызовы
DexClassLoader,InMemoryDexClassLoader,PathClassLoaderс нестандартными путями - признак многостадийной распаковки - Чтение зашифрованных ассетов: обращения к
AssetManager.open()с файлами нехарактерных расширений (в cifrat это былFH.svg, содержащий зашифрованные DEX-файлы - да, SVG-картинка с DEX-ами внутри) - PackageInstaller API: прямая установка второго APK на устройство
- Native-методы без Java-реализации: ключевые функции живут исключительно в .so
a, b, c, но строковые константы часто остаются. Ищем: "ws://", "wss://", "socket", "overlay", "accessibility", "/api/", ".so". Если строки тоже зашифрованы (каждый String проходит через статический метод-дешифратор) - это уже серьёзный индикатор: легитимные SDK редко шифруют строки без документированной причины. DRM и платёжные модули - исключение, но у них обычно понятная подпись и известный вендор.В TaxiSpy CyFirma обнаружила, что WebView URL (
https://taxi.ru) и worker key хранились в .rodata в открытом виде, а вот C2-адрес и Firebase credentials были зашифрованы rolling XOR. Такая избирательность - характерный паттерн: авторы защищают критическую инфраструктуру (C2), но экономят на менее чувствительных данных. Лень - двигатель прогресса, даже у малварщиков.Многостадийная распаковка: извлечение скрытого RAT в SDK
Анализ нативной библиотеки и расшифровка payload
Когда Java-слой выполняет только bootstrap - грузит .so и вызывает native-методы - основная вредоносная логика сидит в нативном коде. Тут начинается работа с radare2.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Rolling XOR с переполнением 32-битного integer и нелинейным доступом к памяти - фирменный приём мобильных RAT: прост в реализации на C, но делает строки невидимыми для
strings, YARA-правил и поверхностного сканирования. C2-адрес, ключи и credentials существуют только в рантайме.В cifrat CERT Polska описала ещё более глубокую схему: второй APK расшифровывался из
res/raw/init_bundle_uzge.bin 32-байтным XOR-ключом, а из него извлекался ассет FH.svg, расшифровываемый RC4-подобным алгоритмом с ключом mLYQ. Финальный результат - DEX-файлы полноценного RAT-модуля. Три стадии шифрования, три разных алгоритма - матрёшка, где каждый следующий слой требует успешной расшифровки предыдущего.Для SilentSDK-сценария после расшифровки нативного слоя ожидаем получить: WebSocket endpoint C2-сервера, ключ аутентификации бота и, возможно, Firebase credentials для резервного канала управления. В TaxiSpy расшифровка выдала
http://193.233.112[.]229 как C2 и Firebase API key - оба значения были полностью скрыты от поверхностного анализа.C2 инфраструктура мобильного вредоноса: анализ коммуникаций
Современные мобильные RAT используют WebSocket для управления - протокол работает поверх HTTP/HTTPS, проходит через корпоративные прокси и файрволы, легко маскируется под легитимный трафик. Для сетевых фильтров это выглядит как обычный веб-сокет к CDN.В cifrat CERT Polska зафиксировала два раздельных WebSocket-канала к серверу
otptrade.world: один для команд управления (запуск кейлоггера, активация камеры, удалённые жесты), второй для передачи данных (стрим экрана, собранные SMS). Разделение каналов - осознанное архитектурное решение: потеря data-канала не прерывает управление, потеря control-канала не сбрасывает активную передачу скриншотов. Грамотно спроектировано, ничего не скажешь.TaxiSpy использовал гибридную модель: основной канал - HTTP POST к endpoint
/api/v1/sync/init с JSON-профилированием устройства (модель, версия ОС, номер телефона, SIM-метаданные, список установленных банковских приложений), а Firebase служил резервным C2. Если основной C2-сервер попадает в блоклист, Firebase-канал продолжает работать через легитимную инфраструктуру Google. Попробуй заблокируй firebaseio.com в корпоративной сети.Для перехвата WebSocket-трафика при динамическом анализе: настраиваем Burp Suite как прокси на эмуляторе, обходим SSL pinning через objection командой
android sslpinning disable, включаем перехват WebSocket во вкладке WebSockets. При анализе фреймов обращаем внимание на бинарные payload (возможно, protobuf или кастомная сериализация), периодические heartbeat-пакеты и структуру команд.Ограничение метода: если RAT реализует certificate pinning не через стандартные Android API, а через собственную проверку в нативном коде - objection не справится. В таком случае придётся патчить .so через radare2 или хукать нативную функцию проверки сертификата через Frida
Interceptor.attach. На практике это встречается у более зрелых семейств, но cifrat и TaxiSpy до такого не дошли.Динамический анализ Android: Frida для перехвата RAT-коммуникаций
Когда статический анализ упирается в многослойную обфускацию кода Android SDK - переходим к динамике. Frida позволяет перехватывать вызовы в рантайме, включая JNI-переходы из Java в нативный код, без модификации APK.Типовой сценарий: мы определили по JNI-экспорту, что native-метод
getServerListNative() возвращает расшифрованный C2-адрес, но восстановление алгоритма шифрования из дизассемблированного ARM-кода займёт часы. Зачем, если можно перехватить результат?
JavaScript:
Java.perform(function() {
var NativeHelper = Java.use("com.silent.sdk.core.NativeHelper");
NativeHelper.getServerListNative.implementation = function() {
var result = this.getServerListNative();
console.log("[*] C2 decrypted: " + result);
return result;
};
});
// Запуск: frida -U -l hook.js -f com.target.app
connect, send, write - используем Interceptor.attach с адресами из radare2.Для комплексного перехвата строковых дешифраторов - находим в jadx метод-дешифратор (обычно статический метод с сигнатурой
String a(String) или String decrypt(byte[])), хукаем его через Frida и логируем каждый результат. За минуту работы приложения получаем полный словарь расшифрованных строк - URL, пути, ключи, имена команд. Вместо часов ручного реверса - одна минута и готовый список.Ограничения динамического анализа Android через Frida: RAT может детектировать инструментацию. Типичные anti-Frida проверки (описаны в OWASP MASVS, раздел MASVS-RESILIENCE): поиск процесса
frida-server через /proc, сканирование /proc/<pid>/maps на frida-agent.so и gadget-библиотеки, проверка имён потоков (gum-js-loop, gmain), проверка TCP-порта 27042, чтение /proc/self/status на ненулевой TracerPid. Обход: переименование бинарника frida-server, использование Frida Gadget (инъекция как .so в APK) вместо серверного режима, пересборка Frida с изменёнными строками и портом. Муторно, но работает.Для TaxiSpy-подобных сэмплов динамический анализ особенно эффективен: rolling XOR с 32-битным overflow и нелинейным доступом к
.rodata сложно воспроизвести на Python без ошибок, если не иметь полную карту памяти секции. Frida даёт готовый результат за минуты.Android trojan SDK detection: индикаторы и автоматизация обнаружения
Маппинг на MITRE ATT&CK
| Тактика | Техника | ID | Проявление в SDK-RAT |
|---|---|---|---|
| Initial Access | Compromise Software Supply Chain | T1195.002 | SDK как легитимная зависимость |
| Defense Evasion (TA0005) | Match Legitimate Resource Name or Location | T1036.005 | Payload маскируется под Google Play Services |
| Defense Evasion (TA0005) | Embedded Payloads | T1027.009 | Зашифрованный payload в .so / assets |
| Collection | Keylogging | T1056.001 | Accessibility Service для перехвата нажатий |
| Collection | Screen Capture | T1113 | Стрим экрана через WebSocket |
| Collection | Data from Local System | T1005 | SMS, контакты, журнал вызовов |
| C2 | Remote Access Tools | T1219 | WebSocket с двунаправленным управлением |
| Exfiltration | Exfiltration Over C2 Channel | T1041 | Данные по тому же WebSocket-каналу |
Что ловить при аудите SDK
MobSF выполняет быструю триаж и находит избыточные разрешения, hardcoded строки, небезопасные API. Но для многостадийных дропперов MobSF пропустит финальный payload - он зашифрован и появляется только в рантайме. Не стоит на него полагаться как на единственный инструмент.Статические индикаторы:
- .so в
lib/с JNI-экспортом, не соответствующим заявленной функциональности SDK - Файлы с высокой энтропией в
assets/илиres/raw/(зашифрованные payload) DexClassLoader/InMemoryDexClassLoaderиз native-методаREQUEST_INSTALL_PACKAGESв манифесте компонента SDK- Receiver на
PACKAGE_ADDED/PACKAGE_REPLACED
- WebSocket-соединения к нестандартным доменам при инициализации SDK
- Accessibility API вызовы из кода, не связанного с UI приложения
- Запись файлов с высокой энтропией во внутреннее хранилище
- HTTP POST с device fingerprint в JSON при первом запуске SDK
Сравнение методов анализа мобильного вредоносного ПО
| Метод | Что находит | Ограничения | Когда применять |
|---|---|---|---|
| MobSF автоскан | Разрешения, hardcoded строки, базовые API | Пропускает многостадийные дропперы | Быстрая первичная триаж |
| jadx + ручной аудит | Java-логику, string references, class hierarchy | Не читает .so, обфускация ломает декомпиляцию | Java-часть SDK |
| radare2 / Ghidra | Нативные библиотеки, XOR/RC4 в .rodata | Требует навыков binary analysis, медленный процесс | .so с криптографией |
| Frida runtime hooks | Расшифрованные строки, реальный C2, runtime payload | Детектируется anti-Frida | Когда статика не даёт C2 |
На практике комбинация всех четырёх методов - единственный надёжный подход. MobSF для триажа, jadx для Java-логики, radare2 для .so, Frida когда всё остальное упёрлось в стену. Пропускать любой из этапов - терять часть картины.
По OWASP MASVS (раздел MASVS-CODE), верификация стороннего SDK включает проверку подписи, анализ debug-символов, оценку обфускации. Раздел MASVS-RESILIENCE описывает защитные механизмы, которые RAT может реализовать для противодействия анализу: anti-tamper, anti-debug, root/emulator detection. Комбинация обоих разделов даёт чеклист для аудита любого мобильного SDK перед интеграцией.
Supply chain через мобильные SDK - вектор, к которому индустрия разработки адаптировалась хуже всего. Google Play Protect ловит известные семейства по сигнатурам, но многостадийный дроппер с шифрованным payload в нативном слое проходит автоматические проверки: финальный RAT не существует в APK до момента выполнения. Команды разработки подключают SDK на основании документации и количества звёзд на GitHub, не заглядывая в манифест. Аудит стороннего кода - не «хорошая практика из чеклиста», а единственный рабочий контроль на стороне разработчика. Три шага - проверка разрешений, анализ .so на предмет JNI-экспорта, мониторинг сетевой активности SDK в изолированном окружении - занимают час и закрывают основной объём supply chain-угроз. Проблема в том, что этот час никто не закладывает в спринт.
Через пару лет supply chain для мобильных SDK станет тем же, чем стал npm для веба - массовым и ежедневным. Навык разбора обфусцированных .so, восстановления XOR-схем и перехвата рантайм-строк через Frida - базовый примитив, который отрабатывается на задачах категории reverse на HackerLab.pro и переносится на анализ любого сэмпла, не только мобильного.