Мобильный реверс: основы анализа приложений

Базовый статический анализ мобильного приложения: как разобрать пакет, где смотреть строки и ресурсы и как найти небезопасное хранение данных в своём приложении.

Статический анализ — изучение приложения без его запуска: разбор файлов пакета, ресурсов, манифеста и кода «в покое». Для мобильных приложений это первый и самый дешёвый способ оценить безопасность — свою или в рамках легального аудита.

Зачем это знать защитнику

Мобильное приложение полностью находится на устройстве пользователя, а значит — у потенциального аналитика. Прежде чем выпускать приложение, полезно посмотреть на него глазами того, кто будет его разбирать: что видно в пакете, какие строки и эндпоинты торчат наружу, как и где приложение хранит данные. Этот урок собирает воедино платформенные знания из раздела и переводит их в практику самопроверки: найти небезопасные места раньше, чем их найдёт кто-то другой. Всё — для своего приложения или легального пентеста с согласием владельца.

Структура пакета: 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, шифрование данных, минимум разрешений, чистый релиз, самоаудит пакета.
Проверьте себя
1. Почему поиск строк (strings + grep) — эффективная первая техника статического анализа мобильного приложения?
AПотому что он расшифровывает зашифрованный код
BПотому что текстовые литералы (URL, ключи, токены) остаются в dex/Mach-O и ресурсах и извлекаются без запуска приложения
CПотому что он требует root и потому надёжен
DПотому что строки в APK не сжимаются специально для анализа
2. Где НЕ следует хранить токен авторизации в мобильном приложении?
AВ Android Keystore
BВ iOS Keychain
CВ SharedPreferences / UserDefaults открытым текстом
DВ зашифрованном виде с ключом из защищённого хранилища
3. Что в AndroidManifest.xml является признаком потенциальной проблемы безопасности в релизной сборке?
AУказание имени приложения
Bandroid:debuggable="true" и экспортированные компоненты без проверки прав
CОбъявление иконки приложения
DСписок поддерживаемых языков