На аудите финтех-приложения под Android 14 стандартная связка «Burp-сертификат в системное хранилище + Wi-Fi прокси» не показала ни одного запроса за полчаса. Приложение использовало OkHttp с кастомным
CertificatePinner, нативную проверку через BoringSSL и root detection на базе SafetyNet. Три уровня защиты, три разных подхода к обходу - и ни один универсальный скрипт с Frida Codeshare не сработал из коробки. Я перепробовал четыре «готовых решения», прежде чем сел писать хуки руками. Динамический анализ Android-приложений на реальных проектах начинается не с запуска готового скрипта, а с методичной работы по каждому слою защиты.Требования к окружению для мобильного пентеста Android
[Применимо: авторизованный аудит мобильных приложений, grey/white box] Подробнее - в нашем статье о пентесте мобильных приложений.Прежде чем лезть в Frida-инструментацию или перехват трафика - среда должна быть настроена. Без этого дальше двигаться нет смысла.
Железо и ОС хоста: Linux, macOS или Windows с Python 3.8+ и
adb из Android Platform Tools. RAM: минимум 8 ГБ при работе с эмулятором, рекомендуется 16 ГБ. Для нативного анализа .so-библиотек потребуется Ghidra или IDA - тут уже десктоп с 16+ ГБ.Устройство: рутованный Android (Pixel 4a/5a - стабильный выбор, проблем с ними меньше всего) или эмулятор Android Studio с образом без Google Play (чтобы работал
adb root). На устройстве - Magisk ≥ 25.0 для управления root и модулями.Софт на хосте:
pip install frida-tools frida - клиентская часть Frida. Версия обязана совпадать с frida-server на устройстве по мажору и минору, иначе получите ошибку при подключении (и будете полчаса гадать, что не так). Burp Suite (Community достаточно для базового анализа) или mitmproxy - для просмотра перехваченного трафика. jadx - для параллельного статического анализа: нужно заранее понять, какой HTTP-клиент использует приложение и как реализован пиннинг.Софт на устройстве: frida-server подходящей архитектуры. Определить архитектуру -
adb shell getprop ro.product.cpu.abi (arm64 для большинства современных устройств). Бинарь скачивается с GitHub releases Frida, распаковывается, пушится: adb push frida-server /data/local/tmp/, затем chmod 755 и запуск через adb shell su -c "/data/local/tmp/frida-server &". Проверка связи - frida-ps -U на хосте должна вернуть список процессов устройства. Если вернула - можно работать.Перехват HTTPS-трафика мобильных приложений: CA-сертификат по версиям Android
Перехват трафика Android-приложения начинается с того, чтобы устройство доверяло сертификату вашего прокси. По классификации MITRE ATT&CK это техника Install Root Certificate (T1553.004, Defense Evasion) - установка корневого сертификата для перехвата зашифрованного канала. Сам перехват - Network Sniffing (T1040, Credential Access). Процедура установки критически зависит от версии Android, и тут начинается веселье.Android 11 и ниже
Работает если: устройство рутовано, системный раздел монтируется на запись (mount -o rw,remount /system).Не работает если: Android 12+ с read-only системным разделом или устройство с Verified Boot без разблокированного загрузчика.
На Android 11 системный раздел перемонтируется в runtime. Экспортируете сертификат Burp в DER, конвертируете в PEM через
openssl x509 -inform DER -in burp.der -out burp.pem, переименовываете файл по хешу субъекта (команда openssl x509 -inform PEM -subject_hash_old -in burp.pem | head -1 даёт значение, добавляете .0), копируете в /system/etc/security/cacerts/. После перезагрузки сертификат появляется в системном хранилище - приложения, доверяющие системным CA, принимают его. Просто и прямолинейно.Android 13 и выше
Работает если: установлен Magisk с модулем Always Trust User Certificates (от Jerome Beckers) или аналогом.Не работает если: устройство без root или приложение использует Network Security Config с жёстко заданными trust anchors, игнорируя системное хранилище.
Начиная с Android 13, Google перевёл системный раздел на read-only на уровне ядра - перемонтировать в runtime невозможно. Решение - Magisk-модуль, который при загрузке копирует пользовательские сертификаты в системное хранилище. Устанавливаете сертификат Burp как пользовательский через настройки безопасности, модуль делает его системным. На Android 14+ процедура усложняется - по данным исследования Tim Perry (HTTP Toolkit), требуется модифицированный подход через init-скрипты Magisk.
После установки CA проверьте, появился ли трафик в прокси. Если да - пиннинга нет, переходите к анализу бизнес-логики. Если нет - впереди обход SSL Pinning.
Frida-инструментация Android: от установки до первого хука
Frida - фреймворк динамической инструментации, который внедряет JavaScript-код в работающий процесс. В терминах MITRE ATT&CK это сочетание Process Injection (T1055, Defense Evasion) и Hooking (T1179, Credential Access) - мы внедряемся в адресное пространство приложения и перехватываем вызовы функций в runtime.Два режима работы:
frida-server на рутованном устройстве - слушает на порту 27042, принимает команды от хоста. Штатный режим для лабораторного пентеста.
frida-gadget - shared library, встраиваемая в APK через repacking. Используется когда root недоступен (корпоративное устройство клиента). Objection автоматизирует процесс:
objection patchapk -s target.apk вставляет gadget и перепаковывает APK.Работает если: frida-server запущен с root, версия клиента и сервера совпадают, SELinux не блокирует выполнение.
Не работает если: приложение детектирует Frida - проверяет
/proc на наличие frida-server, сканирует порт 27042, ищет характерные строки в памяти процесса. По данным исследования Approov (Frida Detection & Prevention), защитные SDK обнаруживают Frida через проверку загруженных библиотек и Debugger Evasion (T1622). На практике банковские приложения детектят Frida в 7 из 10 случаев - приходится выкручиваться.Базовая проверка:
frida-ps -Ua покажет список установленных приложений с идентификаторами пакетов. Подключение к целевому приложению - frida -U -f com.target.app --no-pause -l script.js. Флаг -f запускает приложение заново (spawn mode), --no-pause возобновляет выполнение немедленно. Spawn mode критичен: если приложение выполняет root detection или integrity check при старте, этот режим позволяет перехватить проверки до срабатывания.Обход SSL Pinning Android: техники по типам реализации
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
есть несколько перегрузок (overload). В OkHttp 4.x сигнатура может отличаться от 3.x. Если скрипт падает с ошибкой
overload not found - откройте приложение в jadx, найдите класс okhttp3.CertificatePinner и посмотрите, какие варианты check() там реально присутствуют. По данным NetSPI, расхождение перегрузок - самая частая причина отказа «универсального» скрипта на конкретном APK. Я с этим сталкивался раза три за последний год - каждый раз приходилось лезть в jadx и сверять сигнатуры.Для TrustKit от DataTheorem подход аналогичен: хукается метод
verify класса com.datatheorem.android.trustkit.pinning.OkHostnameVerifier с возвратом true. Если библиотека незнакомая - frida-trace -U -f com.target.app -j '[I]![/I]certificate*' для трассировки всех методов, связанных с сертификатами. Вывод покажет, какой именно класс и метод отвечает за проверку.Скрипт frida-multiple-unpinning от Maurizio Siddu (доступен через Frida Codeshare) закрывает сразу несколько реализаций: Java TrustManager, OkHttp, Retrofit, Appcelerator и частично Flutter. Хорошая отправная точка, но на приложениях с кастомной логикой часто даёт промах - относитесь к нему как к первой попытке, а не как к решению.
Когда универсальные скрипты не работают: динамический анализ APK с нативным пиннингом
Отдельная категория - приложения, где certificate pinning реализован не в Java-слое, а в нативном коде. Тут начинается настоящая работа.Flutter-приложения используют
dart:io HttpClient, который работает через нативный стек BoringSSL и не подчиняется ни системному прокси, ни Java TrustManager. Даже при обходе всех Java-хуков трафик Flutter-модуля просто не пойдёт через Burp - он его в упор не видит. По данным исследования Just Mobile Security, для Flutter эффективен инструмент frida4burp - набор Frida-скриптов, который перенаправляет сокеты напрямую в Burp через runtime socket redirection, минуя системные настройки прокси. Принципиально другой подход: вместо обхода пиннинга перенаправляются сетевые вызовы на уровне сокетов.Приложения с C/C++ сетевым слоем - банковские приложения иногда выносят критичную логику (авторизация, подпись транзакций) в нативные библиотеки (.so), где SSL реализован напрямую через BoringSSL или OpenSSL. Тут потребуется
Interceptor.attach() вместо Java.perform() - работа с адресами функций в .so. Адреса вытаскиваются через Module.findExportByName() или анализом в Ghidra. Целевые функции - SSL_CTX_set_custom_verify или ssl_verify_peer_cert. Универсального скрипта нет - каждый случай требует ручного реверс-инжиниринга Android-приложения. Один .so может занять полдня в Ghidra, прежде чем найдёшь нужную функцию.Типичные ошибки при перехвате трафика Android
Версия frida-tools не совпадает с frida-server. ОшибкиFailed to enumerate processes или unable to communicate with remote frida-server - первое, что проверяется. frida --version и frida-server --version должны показывать одинаковый мажор и минор. Банально, но на это тратится больше всего нервов.Приложение падает при запуске с Frida. Часто это root detection или anti-tampering. Решения: (1) Magisk в режиме Zygisk DenyList для скрытия root от конкретного пакета, (2) Frida-скрипт обхода root detection - хук
java.io.File.exists для путей /su, /data/local/tmp/frida-server, (3) Frida Gadget вместо frida-server - менее детектируем. На одном проекте пришлось комбинировать все три подхода, прежде чем приложение перестало падать.Часть запросов не видна в прокси. Возможные причины: приложение использует certificate transparency для отдельных эндпоинтов, WebSocket-трафик не перехватывается Burp (используйте OWASP ZAP с breakpoints для WebSocket - как описывают специалисты Digital Security, это единственный удобный способ точечно перехватывать конкретные WebSocket-сообщения), или часть логики работает через gRPC/Protobuf, и Burp показывает бинарные данные без расшифровки.
Прокси настроен, приложение показывает «нет сети». Проверьте: не поднимает ли приложение локальный VPN-сервис для DNS-фильтрации, и принимает ли Burp-listener соединения на всех интерфейсах (
0.0.0.0:8080), а не только на 127.0.0.1.| Метод обхода SSL Pinning | Работает | Не работает | Инструмент |
|---|---|---|---|
| CA в системное хранилище | Android до 11, приложение без пиннинга | Android 13+, любой вид пиннинга | Magisk модуль |
| TrustManager hook | Java-слой пиннинга, SSLContext.init | Нативный пиннинг (BoringSSL) | Frida + JS |
| OkHttp CertificatePinner hook | OkHttp 3.x/4.x | Кастомный HTTP-клиент, OkHttp 2.x | Frida + JS |
| Socket redirection | Flutter, нативный HTTP-стек | Integrity checks на уровне TLS | frida4burp |
| Патч smali-кода | Статическая проверка в Java | Play Integrity, runtime integrity checks | apktool + jadx |
Большинство аудитов мобильных приложений требуют комбинации нескольких методов. Чистый TrustManager-хук покрывает около 40% случаев, OkHttp добавляет ещё 30%, а оставшиеся 30% - кастомные реализации, нативный код и Flutter, где нужен ручной анализ Android-приложения.
Мобильный пентест за последние три года сильно поляризовался. С одной стороны, инструменты доступнее: Frida Codeshare, Objection, frida-multiple-unpinning - запустил и поехал. С другой - разработчики научились защищаться: multi-layer pinning, nonce-based certificate rotation, runtime integrity checks с серверной валидацией. Универсальный скрипт обхода SSL Pinning, который работал в 2020 году на подавляющем большинстве приложений, сейчас закрывает хорошо если половину. Остальное - ручная работа: jadx, анализ smali, поиск конкретного метода проверки, написание точечного хука.
И вот что меня раздражает: большинство отчётов по мобильному пентесту, которые я видел за последний год, заканчиваются формулировкой «SSL Pinning обнаружен, обход не удался». Пентестер попробовал три универсальных скрипта, ни один не сработал, и на этом анализ трафика прекратился. Реальные уязвимости - IDOR, broken auth, утечки токенов в ответах API - остались невидимыми за непройденным пиннингом. Умение написать целевой Frida-хук под конкретную реализацию - это не «продвинутый навык для энтузиастов», это базовое требование к тому, кто берётся за анализ Android-приложений. Без этого половина поверхности атаки остаётся непроверенной, а отчёт превращается в формальность.
Попробуйте взять любое приложение из своего телефона, открыть его в jadx и найти, как реализован пиннинг. Написать хук - дело получаса. Не написать - потерять половину аудита.
Последнее редактирование: