Рассматривается динамический анализ iOS-приложений
В первой статье данной серии мы обсуждали анализ трафика приложений iPhone. Вторая, третья и четвертая части были посвящены подробному анализу небезопасных мест хранения данных на iPhone. В данной статье мы рассмотрим динамический анализ приложений iOS (анализ во время выполнения). Динамический анализ позволяет атакующему манипулировать поведением приложения во время его выполнения, чтобы обойти механизмы безопасности и извлечь из памяти конфиденциальные данные. Перед тем, как перейти собственно к анализу, нам сначала нужно рассмотреть архитектуру приложения iOS и защитные механизмы, действующие во время его выполнения.
Архитектура приложений iOS
Приложение iOS представляет собой zip-архив с расширением .ipa. Архив содержит исполняемый двоичный файл и файл iTunesArtwork, который используется iTunes для управления приложением. Ниже показана типичная структура приложения iOS.
Папка в директории Payload, имя которой заканчивается на .app, содержит двоичный файл приложения, все ресурсы приложения вроде изображений и аудиозаписей, профиль, определяющий разрешения приложения, и подпись кода.
Двоичный файл приложения iOS скомпилирован под архитектуру ARM и использует файловый формат Mach-O (mach object). Данный файловый формат состоит из трех основных разделов: заголовка, загрузочных команд и сегментов/секций. Ниже показана структура файлового формата Mach-O.
Структура Mach-O файлов iOS-приложения может быть просмотрена на подвергшемся джейлбрейку устройстве с помощью утилиты otool. Otool доступен из пакета Darwin CC Tools в Cydia.
Заголовок
Раздел позволяет идентифицировать файл Mach-O и содержит основную информацию о типе файла вроде целевой архитектуры и флагов, влияющих на интерпретацию остальной части файла. Чтобы просмотреть Mach-O заголовок приложения iOS, подключитесь к iPhone через SSH и выполните команду:
otool –h ApplicationBinary
Вот заголовок Mach-O приложения Facebook для iOS.
Значения cputype и subtype в заголовке Mach-O определяют целевую архитектуру приложения. В показанном примере видно, что приложение Facebook имеет архитектуру ARM7.
ARM7s (iPhone 5) = cputype 12/ subtype 11
ARM7 (iPhone 4 & 4S) = cputype 12/ subtype 9
ARM6 (iPhone 3GS) = cputype 12/ subtype 6
Приложения, которые скомпилированы для нескольких архитектур, содержат более одного файла Mach-O. Соответствующие двоичные файлы также называются универсальными или толстыми. Чтобы посмотреть Mach-O заголовок универсального двоичного файла, выполните в SSH-терминале следующую команду:
otool –arch all -h ApplicationBinary
На рисунке выше видно, что приложение CardInfo скомпилировано для процессоров с архитектурами ARM7 и ARM7s.
Загрузочные команды
Загрузочные команды определяют то, как сегменты файла располагаются в памяти, а также линковочные характеристики файла (связи с библиотеками). Они содержат первоначальную разметку файла в виртуальной памяти, расположение таблицы символов, состояние выполнения главного потока программы и информацию о подключаемых разделяемых библиотеках. Загрузочные команды (LC_ENCRYPTION_INFO) также определяют, зашифрован ли файл. Чтобы просмотреть загрузочные команды, выполните в SSH-терминале следующую строку:
otool –Vl ApplicationBinary
Данные:
Файл Mach-O содержит собственно данные приложения в одном или нескольких сегментах. В каждом сегменте может быть некоторое количество секций, в том числе, нулевое. Каждая секция сегмента содержит код или данные определенного типа. Точное количество сегментов, секций и их расположение в памяти описывается в разделе загрузочных команд.
Механизмы защиты приложений iOS во время выполнения
Платформа iOS предоставляет множество защитных механизмов, например, ASLR, защита от повреждения стека и ARC. Понимание этих механизмов защиты важно для выполнения реверсирования и анализа iOS-приложений.
Рандомизация адресного пространства (ASLR)
ASLR – важный метод противодействия эксплоитам, появившийся в iOS 4.3. ASLR значительно усложняет удаленную эксплуатацию уязвимостей к повреждению памяти за счет рандомизации размещения объектов приложения в памяти. По умолчанию приложения iOS используют ограниченную ASLR, которая рандомизирует размещение только части объектов в памяти. Чтобы задействовать ASLR максимально, приложение должно быть скомпилировано с флагом -fPIE -pie
(в XCode этому флагу соответствует опция «Генерировать зависимый от расположения код»). В последнем выпуске XCode этот флаг выбран по умолчанию. На рисунке ниже показано состояние различных разделов памяти при частичном и полном применении ASLR.
Чтобы определить, было ли приложение скомпилировано с флагом PIE, подключитесь к iPhone по SSH и выполните команду:
otool –Vh ApplicaitonBinary
На рисунке выше в конце вывода мы видим слово PIE. Это означает, что приложение Facebook было скомпилировано с данным флагом.
Защита от повреждения стека
Защита от повреждения стека – это механизм борьбы с эксплоитами, который защищает от атак переполнения стека путем помещения перед локальными переменными некоторого случайного, но известного значения, называемого стековой канарейкой (по аналогии с живыми канарейками, которых брали с собой шахтеры, чтобы проверить отсутствие взрывоопасных газов). При возврате из функции проверяется значение стековой канарейки. В случае переполнения канарейка будет повреждена, и, узнав об этом, приложение сможет защититься от переполнения. Чтобы включить защиту от повреждения стека, приложение нужно скомпилировать с флагом –fstack-protector-all.
Приложения iOS, которые используют стековых канареек, содержат в двоичном коде строки _stack_chk_fail и _stack_chk_guard. Чтобы определить, использует ли приложение защиту от повреждения стека, подключитесь к iPhone по SSH и выполните следующую команду:
otool –I –v ApplicationBinary | grep stack
Данный снимок экрана свидетельствует о том, что приложение Facebook использует защиту от повреждения стека.
Автоматический подсчет ссылок (ARC)
ARC – еще один механизм для борьбы с эксплоитами, введенный в iOS 5. Он защищает приложения от уязвимостей к повреждению памяти путем перекладывания ответственности за управление памятью с разработчика на компилятор. ARC можно включить, установив значение «yes» для опции «Objective-C Automatic Reference Counting». По умолчанию данный механизм включен.
Приложения iOS с включенным ARC содержат в двоичном файле строку _objc_release. Чтобы определить, использует ли приложение ARC, выполните в SSH-терминале следующую команду:
otool –I –v ApplicationBinary | grep _objc_release
Показанный выше снимок экрана говорит о том, что приложение Facebook скомпилировано с поддержкой ARC.
Механизмы защиты во время выполнения создают дополнительный слой безопасности приложения. Поэтому хорошей практикой является явное включение этих механизмов при компиляции приложения, а в ходе тестирования на проникновение стоит проверить их наличие.
Реверсирование приложений iOS
Чаще всего iOS-приложения пишутся на языке Objective-C. Objective-C – это динамический язык, основанный на принципах передачи сообщений между объектами. Поскольку язык является динамическим, все классы, методы и прочие компоненты хранятся внутри двоичного файла. Данная информация может быть извлечена с помощью утилиты class-dump-z, созданной kennytm.
Установка class-dump-z
- На подвергшемся джейлбрейку устройстве установите из Cydia утилиты wget и unzip.
- Подключитесь к iPhone по SSH и выполните указанные ниже команды
wget -U Mozilla/5.0 www.securitylearn.net/wp-content/uploads/tools/iOS/class-dump-z.zip
unzip class-dump-z.zip
mv class-dump-z /usr/bin - Чтобы выгрузить из приложения iOS информацию о классах, перейдите в поддиректорию приложения, заканчивающуюся на .app, и запустите следующую команду:
class-dump-z ApplicationBinary
На рисунке ниже показана выгруженная информация о классах приложения Gmail для iOS. Здесь не содержится каких-либо полезных данных, поскольку двоичный файл зашифрован. Приложения, загруженные из AppStore, шифруются с помощью FairPlay DRM для защиты от пиратства.
Чтобы выяснить, является ли приложение зашифрованным, запустите в SSH-терминале следующие команды:
otool –l ApplicationBinary | grep crypt
cryptid 1 говорит о том, что приложение зашифровано. Для незашифрованных приложений значение cryptid равно 0.
Часто первым шагом при реверсировании iOS-приложений является снятие шифрования. Расшифровка приложения позволяет атакующему лучше понять, как работает приложение, внутреннюю структуру его классов, и подготовить двоичный файл для реверсирования. Изначально незашифрованными являются приложения, которые используют модель распространения in-house или являются самоподписанными.
Расшифровка приложений iOS
Когда iOS-приложение запускается, загрузчик расшифровывает его и загружает в память. Данный факт лег в основу хорошо отлаженного метода, позволяющего снимать с приложения защиту от копирования FairPlay. Процесс расшифровки включает в себя следующие шаги:
- Нахождение смещения и размера зашифрованных данных внутри двоичного файл приложения.
- Нахождение адреса, по которому приложение загружается в память (если оно было скомпилировано с флагом PIE, то этот адрес будет меняться при каждой загрузке).
- Выгрузка расшифрованной части приложения из памяти с помощью отладчика (например, gdb).
- Замещение зашифрованных данных приложения выгруженными расшифрованными данными.
- Изменение значение cryptid на 0.
Весь данный процесс можно автоматизировать с помощью приложений из Cydia, которые называются Clutch и Rasticrac.
Расшифровка iOS-приложения Gmail с помощью Clutch
- На подвергшемся джейлбрейку устройстве зайдите в Cydia и добавьте репозиторий AppAddict.org/repo, перейдя к пункту Manage->Sources.
- Скачайте из Cydia ClutchPatched и IPA Installer.
- Подключитесь к iPhone по SSH и наберите команду ‘Clutch’. Она перечислит все установленные на iPhone приложения.
- Если теперь указать Clutch определенное приложение, он расшифрует его и сохранит расшифрованные данные в файле с расширением ipa внутри папки /var/root/Documents/Cracked/. На рисунке ниже показано, что Clutch взломал приложение Gmail и сохранил расшифрованные данные в файле /var/root/Documents/Cracked/Gmail-v2.2.0.8921.ipa.
- Данный файл ipa можно установить на iPhone прямо из SSH-терминала, используя следующую команду:
installipa –c [iPAPath]
На рисунке ниже показаны выгруженные данные о классах расшифрованного приложения Gmail.
Полный дамп классов расшифрованного приложения позволяет узнать список классов и их методов, что позволяет глубже взглянуть на то, как устроено приложение. Как только дамп классов получен, мы можем искать интересующие нас классы, методы и проводить динамический анализ (анализ во время выполнения).
Динамический анализ через Cycript
Динамический анализ включает в себя реверсирование приложения и анализ его потока управления для обхода блокировок, аутентификации, доступа к конфиденциальной информации в памяти, нарушения логических проверок и доступа к закрытым областям приложения. Objective-C – рефлективный язык, он позволяет модификацию своего поведения во время выполнения. На iPhone поведение приложения во время выполнения можно легко менять с помощью CyCript. CyCript можно найти среди пакетов Cydia.
Cycript – это язык программирования, сочетающий в себе Objective-C и Javascript. Cycript позволяет вмешиваться в процесс ОС и дает доступ ко всем классам, полям и методам выполняющегося приложения.
Перед тем, как приступить к динамическому анализу, необходимо изучить поток выполнения iOS-приложения.
Objective-C по сути является надстройкой над C, поэтому его выполнение начинается с функции main(). Фактически, main() вызывается, когда пользователь нажимает на значок приложения. Главная функция в свою очередь вызывает метод UIApplicationMain. Данный метод инициализирует объект UIApplication, отображает графический интерфейс (окна, представления), создает делегат приложения и запускает цикл обработки сообщений. Делегат приложения отслеживает высокоуровневые действия/события в приложении. С помощью Cycript мы можем подключиться к запущенному процессу и получить доступ к его объекту UIApplication. UIApplication – это синглтон, который представляет приложение и действует как центр управления. Так что, получение доступа к данному объекту – это получение доступа к внутренней структуре приложения.
Возможности Cycript показаны в следующих далее примерах. В целях демонстрации я использовал старую версию приложения Photo Vault. Перед внедрением в процесс с помощью cycript мы сначала выгрузим информацию о классах приложения через class-dump-z.
Доступ к полям объектов через Cycript
Приложение Photo Vault сохраняет конфиденциальность фотографий за счет ограничения доступа по паролю. Когда мы запускаем приложение в первый раз, оно просит пользователя установить пароль. В последующие разы для получения доступа к защищенным фотографиям пользователю нужно ввести правильный пароль. Ниже описаны шаги, как узнать пароль через динамический анализ посредством Cycript.
- Запустим приложение Photo Vault. Оно запросит пароль.
- Подключимся к iPhone по SSH и получим информацию о процессе с помощью команды ps ax.
- Внедримся в процесс, используя команду
cycript –p [PID]
.
Замечание: Если вы знаете имя приложения, вы можете также внедриться в его процесс, используя командуcycript –p [ApplicationName]
.
- В командной строке cycript мы можем получить доступ к экземпляру приложения либо путем вызова метода [UIApplication sharedApplication], либо используя переменную UIApp.
- Чтобы найти делегат приложения, выполним команду UIApp.delegate.
- Найдем в выгруженной информации о классах делегат приложения PhotoVaultAppDelegate и рассмотрим секцию @interface (также полезной будет секция @protocol). Секция @interface содержит объявление всех методов и свойств, а @protocol – группу связанных методов, которые объект может вызвать через свой делегат.
- В делегате приложения содержится интересующее нас свойство – strPass. Запросим значение, хранимое в этом свойстве, набрав в командной строке UIApp.delegate.strPass.
- Ура! Мы получили пароль к фотографиям. Можем ввести его в приложении и получить доступ к защищенным фотографиям пользователя.
Cycript также позволяет модифицировать значения полей, вызывать методы и перезаписывать существующие методы прямо во время выполнения программы.
Это пятая часть серии статей о пентестинге приложений iPhone. В шестой части будет рассмотрен динамический анализ приложений iOS с помощью gdb и подмена методов с помощью Cycript.
Ссылки
- Debunking NSLog Misconceptions oleb.net/blog/2011/06/app-launch-sequence-ios/
- Hacking and Securing iOS Applications by Jonathan Zdziarski
- «Apple iOS 4 Security Evaulation» by Dino Dai Zovi
Подписывайтесь на каналы «SecurityLab» в Telegram и
Яндекс.Дзен, чтобы первыми узнавать о новостях и эксклюзивных материалах по информационной безопасности.