Статья Реверс-инжиниринг iOS приложений: IPA-анализ, class-dump и Frida глазами защитника

Руки оператора на тёмной клавиатуре в свете монитора с сессией Frida REPL. Фосфорно-зелёное свечение экрана, абсолютная темнота вокруг, атмосфера ночной работы.


На аудите финтех-приложения за 40 минут статического анализа IPA-файла мы вытащили три захардкоженных API-ключа, endpoint внутреннего микросервиса и HMAC-секрет для подписи запросов. Ключи работали в продакшене больше восьми месяцев - компания узнала об этом только потому, что заказала пентест мобильного приложения. Потенциальный ущерб: несанкционированный доступ к данным 200+ тысяч клиентов и оборотные штрафы по 152-ФЗ.

Этот кейс не исключение, а типовой результат первых часов реверс-инжиниринга iOS-приложения. Эта статья будет полезна для SOC-инженеров, так и для Blue Team. В ней мы разберёмся, что именно делает атакующий, какие артефакты оставляет и как выстроить detection, чтобы реверс вашего приложения не стал задачей на один вечер.

Место в цепочке атаки: зачем реверсить iOS-приложение​

Реверс-инжиниринг iOS приложений - не самоцель. Это разведка перед атакой на серверную инфраструктуру. Атакующий разбирает бинарник ради конкретных вещей: извлечь секреты (API-ключи, токены, URL внутренних сервисов), понять бизнес-логику (эндпоинты, параметры запросов, клиентская валидация), обойти защитные механизмы (SSL-pinning, jailbreak detection, биометрию) и подготовить серверную атаку (фаззинг API, abuse бизнес-логики).

В терминах MITRE ATT&CK цепочка выглядит так: получение и расшифровка IPA-файла - Deobfuscate/Decode Files or Information (T1140, Defense Evasion) - вызов нативных функций анализа через Native API (T1106, Execution) - перехват методов через Credential API Hooking (T1056.004, Collection / Credential Access) в runtime. При модификации и переподписи приложения добавляется Dylib Hijacking (T1574.004, Defense Evasion / Execution).

Этап атакиИнструментТехника ATT&CKЧто получает атакующий
Распаковка IPAfrida-ios-dump, bagbakT1140 (Deobfuscate/Decode Files or Information)Расшифрованный бинарник без FairPlay DRM
Статический анализclass-dump, otool, stringsT1027 (Obfuscated Files)Классы, методы, строки, URL, ключи
ДизассемблированиеHopper, Ghidra, IDA ProT1106 (Native API)Логика аутентификации, валидации, шифрования
Runtime-перехватFrida, CycriptT1056.004 (Credential API Hooking)Обход pinning, перехват credentials
Anti-debug bypassFrida, lldbT1622 (Debugger Evasion, описана для Windows; на iOS применяется по аналогии)Обход ptrace, sysctl-проверок

Для SOC вывод прямой: реверс iOS-приложения - подготовительный этап к атаке на бэкенд. Если атакующий извлёк API-ключ и endpoint - следующий шаг уже в вашей серверной инфраструктуре.

Требования к окружению​

Для воспроизведения техник ниже (в рамках авторизованного аудита):
  • ОС: macOS 13+ (Ventura или новее) для class-dump, otool, Hopper
  • Устройство: джейлбрейкнутый iPhone - checkra1n (чипы A7–A11) или palera1n (checkm8-устройства A8–A11, iOS 15–17). Минимум 3 GB свободной памяти
  • Frida 16.x:pip install frida-tools на хосте, frida-server соответствующей версии на устройстве
  • class-dump: оригинальный class-dump (nygard) устарел; для современных iOS нужны форки (class-dump-dyld, ICDump) или встроенные возможности Hopper/Ghidra. Swift-классы class-dump извлекает частично - понадобится swift-demangle
  • Дизассемблер: Hopper Disassembler v5 (Personal/Commercial лицензия, актуальные цены на hopperapp.com) или Ghidra (бесплатный)
  • Прокси: Burp Suite для перехвата трафика после обхода pinning
  • SSH: OpenSSH на устройстве через Cydia/Sileo
Для Blue Team, которой нужно оценить масштаб угрозы без сборки полного стенда: macOS с class-dump и Hopper хватит за глаза - статический анализ IPA не требует физического устройства.

Статический анализ IPA файлов iOS: что находит атакующий за первый час​

1780399896522.webp

Структура IPA и binary analysis Mach-O​

IPA - ZIP-архив с предсказуемой структурой. Внутри Payload/<AppName>.app/ лежит основной Mach-O бинарник (ARM64-код), рядом - Info.plist, фреймворки, ресурсы. Первые действия атакующего занимают минуты:

Распаковка: unzip app.ipa -d output/. Определение архитектуры: otool -hv <binary> - в выводе будет ARM64 (современные устройства), реже fat binary с armv7 + arm64. Список зависимостей: otool -L <binary> - показывает linked frameworks. Наличие CryptoKit, Security.framework, CommonCrypto указывает на работу с криптографией. Нестандартные .dylib - потенциально интересные сторонние библиотеки.

Извлечение строк: strings <binary> | grep -iE 'api|key|secret|token|http' - в незащищённых приложениях выдаёт URL бэкенда, ключи и иногда пароли открытым текстом. Альтернатива - rabin2 -zz <binary> из набора radare2 (текущая версия 6.1.5, проект активно поддерживается).

По данным OWASP MASVS (раздел MASVS-CODE), production-сборки не должны содержать debug-символов и незашифрованных чувствительных строк. На практике - значительная часть аудируемых приложений эту проверку проваливает.

class-dump iOS: чтение Objective-C интерфейсов​

class-dump извлекает заголовки классов из Mach-O бинарника. Для Objective-C работает почти идеально: runtime хранит все имена классов, методов и свойств. Для чистого Swift ситуация хуже - Swift-символы используют name mangling и требуют swift-demangle или class-dump-swift. Как отмечают в руководстве Corellium, «the older version of class-dump won't work if there is Swift code within the binary»«Более старая версия class-dump не сработает, если в бинарном файле есть код Swift» - поэтому архитектуру и язык стоит определять заранее через otool.

Типичный выход class-dump для приложения на Objective-C:
Код:
@interface AuthenticationManager : NSObject
+ (BOOL)validateToken:(NSString *)token;
- (void)loginWithUsername:(NSString *)user password:(NSString *)pass;
- (BOOL)isJailbroken;
- (void)setupCertificatePinning;
@property (nonatomic, copy) NSString *apiBaseURL;
@property (nonatomic, copy) NSString *apiSecret;
@end
Что видит атакующий: имена методов (isJailbroken, setupCertificatePinning) дают точную карту защитных механизмов. Свойства типа apiSecret - прямое указание на hardcoded секрет. Метод loginWithUsername:password: - цель для Frida-хука.

Если в дампе классов видны читаемые имена вроде validatePurchase, checkLicenseKey, bypassDetection - приложение, по сути, поставляется с документацией для атакующего. OWASP MASVS-RESILIENCE рекомендует обфускацию символов и strip debug-информации. На деле - мало кто это делает.

Hopper дизассемблер iOS: навигация по бизнес-логике​

Hopper Disassembler (и бесплатная альтернатива Ghidra) позволяет перейти от списка методов к пониманию их внутренней логики. Как отмечает Y-Security в руководстве по OWASP MASTG, «no decompilers are available for iOS apps»«Не существует декомпилятора для iOS приложений» в полном смысле - псевдокод из Ghidra/Hopper приближён к исходному, но не эквивалентен ему. Для защитников это значит: обфускация замедляет атакующего, но не останавливает.

На ARM64-дизассемблере я обычно ищу три вещи.

Первое - ветвления в проверках безопасности. Методы isJailbroken, checkIntegrity. Типичный паттерн: серия вызовов fileExistsAtPath: с путями /Applications/Cydia.app, /usr/sbin/sshd, /Library/MobileSubstrate/MobileSubstrate.dylib. Если метод возвращает BOOL - в ARM64 это один cmp + b.ne, который патчится за секунды.

Второе - криптографические константы. Строки, передаваемые в CCCrypt, SecKeyEncrypt или кастомные функции шифрования. Ключи часто валяются как статические строки в секции __cstring. Перекрёстные ссылки (cross-references) от этих строк ведут прямо к функциям шифрования.

Третье - сетевые вызовы. Xrefs от строк с URL к методам NSURLSession. Это даёт полную карту API-эндпоинтов, включая внутренние, не документированные публично.

Разница между анализом Objective-C и Swift принципиальна: Objective-C бинарники сохраняют полные имена селекторов в __objc_methname, что делает дизассемблированный код почти читаемым. Swift-бинарники используют name mangling (имена вида $s7MyApp14ViewControllerC), и Hopper/Ghidra восстанавливают их частично. Приложение на Swift получает базовый уровень obfuscation «бесплатно», но полагаться на это как на защиту - иллюзия.

Динамическая инструментация Frida iOS: перехват в runtime

1780400297802.webp

Статический анализ даёт карту - динамическая инструментация Frida даёт результат. Frida позволяет внедрять JavaScript-код в работающий процесс на джейлбрейкнутом устройстве, перехватывая любой вызов метода без модификации бинарника.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Обход jailbreak detection - если class-dump показал метод isJailbroken, его возврат подменяется за секунды: достаточно переопределить implementation через ObjC.classes. Это техника Credential API Hooking (T1056.004).

В корпоративном контексте риск конкретный: скомпрометированное устройство сотрудника, на котором отключена jailbreak-проверка MDM-управляемого приложения, становится вектором утечки корпоративных данных. Атакующему даже не нужно атаковать сервер - достаточно перехватить трафик приложения на подконтрольном устройстве.

Обход биометрии - хук на evaluatePolicy:localizedReason:reply: класса LAContext (фреймворк LocalAuthentication) подменяет результат проверки Touch ID / Face ID. Атакующий получает доступ к функциям, защищённым биометрией, без физического присутствия владельца.

Detection и hardening: что контролировать на стороне защиты​

Серверная детекция: что видит SOC​

Реверс приложения происходит на устройстве атакующего - напрямую SOC его не увидит. Но последствия заметны в серверных логах:
  1. Аномальные User-Agent и заголовки - после обхода pinning трафик идёт через Burp Suite или mitmproxy. User-Agent может не совпадать с валидным значением приложения. Правило корреляции: алерт на API-запросы с нестандартным UA при валидном токене авторизации
  2. Replay и манипуляция параметрами - если атакующий понял структуру API через реверс, он подставляет чужие ID, меняет суммы, перебирает параметры. Корреляция: всплеск 4xx/5xx ошибок с одного токена за короткий период
  3. Использование отозванных или hardcoded ключей - если в бинарнике был захардкожен API-ключ, который вы ротировали, а запросы с ним продолжают приходить - это прямой IOC
  4. Географические аномалии - запросы от одного пользователя одновременно из разных геолокаций
  5. Отсутствие device attestation - Apple App Attest позволяет серверу верифицировать, что запрос пришёл с легитимного устройства с неизменённым приложением. Отсутствие attestation-маркера при включённой проверке - IOC

Клиентские проверки и их ограничения​

Клиентские проверки замедляют атакующего, но не останавливают. Frida обходит любую проверку - вопрос только в затраченном времени:

ПроверкаЧто детектируетСпособ обходаСложность обхода
fileExists /Applications/Cydia.appJailbreak (базовый)Frida hook на NSFileManager + C-функции stat/access/fopenЛёгкая
_dyld_image_count - проверка загруженных dylibFrida/Substrate injectionFrida Stalker, rename dylibСредняя
ptrace(PT_DENY_ATTACH)Debugger attachmentFrida использует Mach API, не ptrace - PT_DENY_ATTACH на неё не влияет; для lldb - хук syscall ptrace через dyld interposeЛёгкая (Frida), средняя (lldb)
sysctl для обнаружения отладчикаlldb, gdbХук sysctlЛёгкая
Проверка порта 27042Frida default portСмена порта при запускеТривиальная
Integrity check (хеш бинарника)Патчинг binaryПересчёт хеша после модификацииСредняя
Apple App Attest (server-side)Модификация приложенияТребует обхода Secure EnclaveВысокая

Для SOC критичны серверные detection-правила - клиентские проверки покупают время, но гарантий не дают.

Hardening-чеклист по OWASP MASVS-RESILIENCE

Чеклист для передачи команде разработки - конкретные задачи, а не абстрактные пожелания:
  1. Strip debug-символы перед релизом - strip -S <binary>, включить Strip Debug Symbols в Xcode Build Settings
  2. Шифровать чувствительные строки в runtime: не let key = "abc123", а расшифровка из зашифрованного массива при первом обращении (MASVS-STORAGE)
  3. Использовать final для критичных классов в Swift - предотвращает swizzling через наследование
  4. Реализовать многослойную jailbreak-detection: не только проверка файлов, но и sandbox integrity, fork() check, dyld-проверки
  5. Внедрить ptrace(PT_DENY_ATTACH) и sysctl-проверки - блокирует lldb/gdb (обход требует hook syscall), но не влияет на Frida, которая использует Mach API (T1622, Debugger Evasion)
  6. Подключить Apple App Attest для серверной верификации целостности - единственная проверка с высоким порогом обхода
  7. Реализовать certificate pinning через NSURLSessionDelegate с проверкой SPKI-хеша (MASVS-NETWORK)
  8. Не хранить секреты в бинарнике: Keychain для токенов, runtime-получение конфигурации с сервера (MASVS-STORAGE)
  9. Применить control flow obfuscation для критичных методов - усложняет анализ в Hopper/Ghidra (защита от T1027)
  10. Провести self-аудит IPA перед релизом: прогнать class-dump и strings на собственной сборке - если вы видите секреты, атакующий тоже их увидит
Чеклист покрывает требования OWASP MASVS-RESILIENCE и MASVS-CODE. Передавайте его разработчикам с конкретными тикетами - абстрактная формулировка «улучшить безопасность» не работает.

Заключение

Два года назад я начал включать в отчёты по пентесту мобильных приложений метрику «время до первого секрета» - сколько минут от получения IPA до извлечения первого чувствительного значения. Медиана для корпоративных iOS-приложений - 25 минут. С базовой обфускацией - 2–3 часа. С полноценной защитой уровня MASVS-RESILIENCE L2 - от 8 часов до «не удалось за отведённое время аудита».

Проблема не в инструментах атакующего: class-dump, Hopper и Frida доступны каждому. Проблема в том, что большинство команд разработки воспринимают клиентскую защиту как задачу «на потом». Jailbreak detection из пяти строк на проверку пути к Cydia - не защита, а самоуспокоение. Атакующий обходит её быстрее, чем разработчик написал.

Единственная рабочая стратегия - не доверять клиенту вообще ничего: серверная валидация каждого параметра, App Attest, ротация ключей, мониторинг API-аномалий. Клиентские проверки - замедлитель, не барьер. И если SOC не мониторит API на паттерны реверснутого приложения (нестандартные UA, replay, манипуляция ID), об инциденте вы узнаете из тикета клиента, а не из алерта.

Прогоните strings и class-dump на своей последней production-сборке прямо сейчас. Если в выводе мелькнул хоть один ключ или внутренний URL - у вас та же проблема, что и у финтех-компании из начала статьи. Только вы пока об этом не знаете. Если хочется отработать полную цепочку реверса iOS-приложения в безопасной среде - на codeby.net разбирают конкретные подходы к detection мобильных API-аномалий под разные стеки.
 
Последнее редактирование модератором:
Мы в соцсетях:

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

Похожие темы

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

HackerLab