Экран старого CRT-монитора в темноте показывает декомпилированный Java-код с деревом классов и строками перехваченного соединения. Зелёное свечение фосфора, горизонтальные полосы развёртки, глубока...


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-подобного сценария:
  1. Initial Access - разработчик подключает SDK из скомпрометированного источника (T1195.002)
  2. Execution - при инициализации SDK вызывает System.loadLibrary(), нативная библиотека расшифровывает embedded payload
  3. Defense Evasion - второй этап маскируется под системный компонент: Google Play Services, analytics framework (T1036.005); зашифрованный payload в нативной библиотеке скрывает вредоносный код от статического анализа (T1027.009)
  4. Collection - финальный RAT собирает SMS, контакты, нажатия клавиш (T1056.001), скриншоты (T1113), файлы устройства (T1005)
  5. Command and Control - управление по WebSocket через двунаправленный канал (T1219)
  6. Exfiltration - данные уходят по тому же C2-каналу (T1041)
Принципиальная разница с обычным трояном: пользователь ничего подозрительного не ставит. Приложение - легитимное, из официального магазина. RAT прибывает внутри SDK, которому разработчик доверяет. В случае cifrat, по данным CERT Polska, дроппер распространялся через фейковую страницу обновления Booking.com с URL 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-gui1.5+Декомпиляция DEX в JavaАктивный проект
apktool2.9+Распаковка/сборка APK, smaliАктивный проект
radare26.1.5Анализ нативных .so библиотекАктивный проект
Fridaактуальная из pipRuntime хуки, перехват JNI-вызововАктивный проект
objectionактуальная из pipОбход SSL pinning, explorationАктивный проект
MobSF4.xАвтоматический статический/динамический сканАктивный проект
Burp SuiteCommunity или 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
По OWASP MASVS (раздел MASVS-PLATFORM), верификация стороннего кода на уровне манифеста - первый обязательный этап аудита. SDK, запрашивающий разрешения, не связанные с заявленной функциональностью, требует углублённого анализа. Тут не бывает «ну может им правда надо» - если SDK аналитики просит 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
Frida перехватывает Java-обёртку вызова, а расшифровка происходит внутри .so - нам остаётся прочитать результат. Для более глубоких хуков - на уровне libc-вызовов 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 AccessCompromise Software Supply ChainT1195.002SDK как легитимная зависимость
Defense Evasion (TA0005)Match Legitimate Resource Name or LocationT1036.005Payload маскируется под Google Play Services
Defense Evasion (TA0005)Embedded PayloadsT1027.009Зашифрованный payload в .so / assets
CollectionKeyloggingT1056.001Accessibility Service для перехвата нажатий
CollectionScreen CaptureT1113Стрим экрана через WebSocket
CollectionData from Local SystemT1005SMS, контакты, журнал вызовов
C2Remote Access ToolsT1219WebSocket с двунаправленным управлением
ExfiltrationExfiltration Over C2 ChannelT1041Данные по тому же 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 и переносится на анализ любого сэмпла, не только мобильного.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab