Мобильный реверс: основы анализа приложений
Базовый статический анализ мобильного приложения: как разобрать пакет, где смотреть строки и ресурсы и как найти небезопасное хранение данных в своём приложении.
Статический анализ — изучение приложения без его запуска: разбор файлов пакета, ресурсов, манифеста и кода «в покое». Для мобильных приложений это первый и самый дешёвый способ оценить безопасность — свою или в рамках легального аудита.
Зачем это знать защитнику
Мобильное приложение полностью находится на устройстве пользователя, а значит — у потенциального аналитика. Прежде чем выпускать приложение, полезно посмотреть на него глазами того, кто будет его разбирать: что видно в пакете, какие строки и эндпоинты торчат наружу, как и где приложение хранит данные. Этот урок собирает воедино платформенные знания из раздела и переводит их в практику самопроверки: найти небезопасные места раньше, чем их найдёт кто-то другой. Всё — для своего приложения или легального пентеста с согласием владельца.
Структура пакета: APK и IPA
Оба формата — это архивы, и оба распаковываются стандартно. APK (Android) — ZIP с classes.dex, AndroidManifest.xml, ресурсами (res/, resources.arsc) и нативными библиотеками. IPA (iOS) — тоже ZIP; внутри папка Payload/AppName.app/ с исполняемым Mach-O бинарником, файлом Info.plist, ассетами и ресурсами. Первый шаг анализа — просто распаковать и осмотреть содержимое своего пакета:
# посмотреть, что внутри пакета (свой файл)
unzip -l myapp.apk | head
unzip -l MyApp.ipa | head
Уже список файлов многое говорит: какие библиотеки подключены, есть ли подозрительные ресурсы, не забыты ли тестовые файлы.
Ресурсы и строки
Самая результативная и простая техника — поиск строк. В скомпилированном коде и ресурсах остаются текстовые литералы: URL, ключи, сообщения, имена параметров. На Android их извлекают из dex и resources.arsc, на iOS — из Mach-O и Info.plist. Базовый инструмент — утилита strings плюс греп по интересным шаблонам (иллюстрация на своём приложении):
# вытащить читаемые строки и отфильтровать подозрительные (свой бинарник)
strings -n 6 classes.dex | grep -iE "http(s)?://|api[_-]?key|secret|password|token"
Что ищут защитники в выводе: захардкоженные эндпоинты бэкенда, ключи и токены, отладочные URL, упоминания внутренних сервисов. На iOS аналогично смотрят Info.plist (например, объявленные схемы URL, домены ATS-исключений) и строки бинарника. Если приложение «светит» секретом в строках — это находка, которую нужно устранить выносом секрета на сервер.
Манифест и разрешения
Манифест/конфиг приложения многое сообщает о его поведении. На Android в AndroidManifest.xml смотрят:
- Разрешения — не запрашивает ли приложение лишнего (геолокация, контакты, SMS), что расширяет поверхность риска.
- Экспортированные компоненты —
activity/service/receiverсandroid:exported="true"доступны другим приложениям; если они выполняют чувствительные действия без проверки, это дыра. - Флаги отладки и бэкапа —
android:debuggable="true"иandroid:allowBackup="true"в релизе опасны: первый упрощает анализ, второй позволяет вытащить данные приложения через резервную копию.
На iOS роль конфигурации играет Info.plist: список разрешений с пояснениями, схемы URL, настройки сетевой безопасности (ATS). Принцип тот же — минимум разрешений и никаких отладочных послаблений в релизе.
Поиск небезопасного хранения данных
Частая и опасная проблема мобильных приложений — хранение чувствительных данных в открытом виде на устройстве. Что проверяют в своём приложении (статически — по коду и ресурсам — и при желании динамически — по файлам на тестовом устройстве):
| Где | Риск | Как правильно |
| SharedPreferences / UserDefaults | токены и пароли открытым текстом | хранить секреты в Keystore (Android) / Keychain (iOS) |
| SQLite-база в песочнице | персональные данные без шифрования | шифровать чувствительные поля/базу |
| Логи (logcat / консоль) | утечка токенов и PII в логи | не логировать секреты, чистить debug-логи к релизу |
| Файлы в открытых каталогах | данные доступны при бэкапе/доступе к ФС | минимизировать, шифровать, не класть в общий доступ |
Признаки в коде, на которые обращают внимание при статическом анализе: запись токена в SharedPreferences без шифрования, ключ шифрования рядом с зашифрованными данными, логирование ответов сервера целиком. Каждый такой признак — пункт для исправления.
Как это работает под капотом
Статический анализ опирается на то, что форматы пакетов и компиляции — открытые и предсказуемые. ZIP-контейнер распаковывается стандартно; dex и Mach-O имеют документированную структуру с таблицами символов и пулами строк, поэтому текстовые литералы извлекаются без выполнения кода. Манифест на Android в APK хранится в бинарном XML, но инструменты вроде apktool или aapt декодируют его обратно в читаемый XML. Декомпиляторы (jadx для Android) дополнительно восстанавливают логику из байт-кода, как разбиралось в уроке про Java/Android. Динамический анализ идёт дальше — наблюдает за приложением во время работы (файлы в песочнице, сетевой трафик через прокси, перехват вызовов), но даже без него статика даёт большую часть быстрых находок: строки, разрешения, флаги, очевидно небезопасное хранение. Именно поэтому первый шаг самопроверки приложения — статический разбор пакета.
Как защититься
Чек-лист автора мобильного приложения.
- Секреты — на сервер. API-ключи и токены не зашивайте в код и ресурсы: они извлекаются из строк. Клиент получает доступ через аутентифицированный бэкенд.
- Правильное хранилище секретов. Токены и ключи — в Android Keystore / iOS Keychain, а не в SharedPreferences/UserDefaults открытым текстом.
- Шифруйте чувствительные данные. Персональные данные в локальной базе/файлах — в зашифрованном виде, ключ — в защищённом хранилище.
- Минимум разрешений и экспортов. Запрашивайте только нужные разрешения; не экспортируйте компоненты без необходимости и проверяйте права у экспортированных.
- Без отладочных послаблений в релизе. Снимите
debuggable, ограничьтеallowBackup, уберите подробные логи с секретами. - Минификация и серверная авторизация. R8/ProGuard на Android усложняют чтение; любые проверки прав дублируйте на сервере.
- Проводите самоаудит. Распакуйте свой релизный пакет, прогоните поиск строк и просмотр манифеста — найдите проблемы до публикации.
Юридическое напоминание: анализировать чужие приложения можно только в рамках закона и согласия владельца; для своего приложения и легального пентеста ограничений нет.
Итоги
- APK и IPA — это ZIP-архивы; статический анализ начинается с распаковки и осмотра содержимого.
- Поиск строк (
strings+ греп) быстро вскрывает зашитые URL, ключи и токены. - Манифест/
Info.plistпоказывают разрешения, экспортированные компоненты и опасные debug-флаги. - Небезопасное хранение (открытые токены в SharedPreferences/UserDefaults, нешифрованные базы, утечки в логи) — частая и устранимая проблема.
- Защита: секреты на сервер, Keystore/Keychain, шифрование данных, минимум разрешений, чистый релиз, самоаудит пакета.