взлом приложений на айфон
Ломаем iOS-приложение. Часть 1
Вы хорошо поработали, и вот ваше приложение в App Store!
Disclaimer
Цель данного урока — не сделать вас хакером, а показать, как злоумышленники могут обвести вас вокруг пальца. В статье пропущена кое-какая инфа, необходимая для взлома реального приложения на девайсе. Будем мучить симулятор (кстати, это вроде бы даже законно [citation needed] ).
Disclaimer от переводчика: из оригинального текста убрано много «воды» и отсылок к Голливуду (и так длинно). Добавлен ряд ключевых пояснений.
Ни одно приложение не является безопасным! Если кто-то действительно захочет найти у вас уязвимости, то он их найдёт. Нет гарантированного способа предотвратить атаку. Разве что, не выпускать приложение. Но есть отличные способы помешать взломщикам. (По мнению автора, им надоест, и они пойдут спать искать более лёгкую добычу, ага. — Прим. пер.)
Перед тем, как читать дальше, вы должны примерно понимать, что такое терминал, а также Objective C и Cocoa (впрочем, особо много кода не будет).
Приступим
Нам понадобится:
1. Утилита class-dump-z;
2. Прокси для отладки по сети, например, Charles (триал-версия отличается надоедливыми сообщениями и работает максимум 30 минут за 1 сеанс). В комментах к исходнику статьи советуют альтернативу Чарльзу — Burpsuite.
Чтобы вы творчески подошли к процессу, предлагаю вам сценарий. Представьте: вышло новое приложение для айпада — «Собиратель мемов» (Meme Collector). Всем нравится. Но вам шепнули на ухо, что встроенные покупки вытянут из вас значительную сумму денег.
В общем, вы задумали получить платный контент (мемы) бесплатно. Есть несколько направлений, куда можно двигаться, мы поговорим о них — и о соответствующих методах защиты.
Что к чему? «Карта» приложения (application mapping)
Взглянем на приложение с высоты птичьего полёта! Что оно делает, с точки зрения пользователя? Какова его основная структура?
Откройте проект Meme Collector в своей любимой IDE или в Xcode (не реклама).
Мы будем запускать приложение в конфигурации Release.
Xcode: Product > Scheme > Edit scheme… (⌘ Build Configuration: Release.
AppCode: Run > Edit configurations… > Configuration: Release.
Запустите приложение на симуляторе iPad (⌘R). А теперь забудьте, что у вас есть исходники, вы — юзер. Откроется одно из двух:
Этот странный интерфейс позволяет «купить» мем по тапу на него, а также показывает число покупок данного мема и остаток денег на вашем счёте. От переводчика: нажав кнопку «Purchase Currency», я реально задумался: а не вводил ли я Apple ID на симуляторе?
…но вспомнил, что у меня к US-аккаунту не привязана кредитка. 🙂 Русский бы сказал цену в рублях.
В общем, всё просто. Есть «игровая валюта», и вы (типа взломщик) не хотите отдавать за неё реальные деньги. Наша цель — получить больше мемов, не нажимая кнопку «Purchase Currency».
Мы примерно поняли, что делает приложение, давайте заглянем глубже. Что ещё мы можем узнать?
Перейдите в папку симулятора iOS: (вместо 7.0.3 — ваша версия)
Здесь лежат все приложения, которые вы запускали в симуляторе. Их там может быть много. Как найти Meme Collector?
Вариант 1. Если вы только что запускали Meme Collector, то он лежит в папке с самой новой датой модификации. Просто перейдите в неё:
Вариант 2. Взять и найти:
Тут есть исполняемый файл, который так и называется: Meme Collector (без расширения). Посмотрим, на какие фреймворки (frameworks) и общие библиотеки (shared libraries) имеются в нём ссылки. Нам поможет стандартная утилита otool :
Мм, интересно, приложение использует фреймворк Store Kit — встроенные покупки? Ну-ка, идём дальше. Запускаем утилиту class-dump-z:
И откроем полученный файл в стандартном гуёвом редакторе:
Изучение дампа классов серьёзного проекта — чаще всего утомительное занятие. Но оно может дать потрясающую картину внутреннего устройства приложения!
Итак, мой юный следопыт! Найдите-ка мне все синглтоны в приложении.
Если встретите интересный синглтон, изучите все его методы.
(Видимо, «интересный» = «похоже, имеющий отношение к логике приложения». — Прим. пер.)
Точно нашли? Посмотрите у себя внимательнее. Их там около четырёх штук.
Взломщики часто делают то, что вы сейчас сделали — ищут определённые слова в дампе класса. Например, если они хотят узнать, есть ли в приложении логика, завязанная на джейлбрейк девайса, то поиск по словам ‘jailbroken’, ‘security’ и т.д. может дать быстрый ответ.
Как это предотвратить?
Есть две новости. Начну с хорошей.
Apple делает это за вас автоматически. Когда вы отправляете приложение в App Store, они шифруют ваши бинарники с использованием DRM-технологии под названием FairPlay. Если вы сдампите class-dump-z’ом зашифрованный бинарник, то получите… тарабарщину.
Плохая новость: обойти эту защиту довольно легко! Дело на 10 минут (вручную), а ещё есть средства автоматизировать сей процесс. В общем, будьте уверены, ваше приложение расшифруют и увидят названия всех ваших классов, методов, протоколов и т.д.
Plist-файлы: уязвимы!
Мы кое-что узнали о приложении. Теперь поищем всё, что плохо лежит. Разработчикам свойственно ошибаться. Злоумышленникам свойственно использовать эти ошибки в своих целях.
Посмотрим, какие plist’ы у нас есть?
(напомню, мы всё ещё находимся в папке бандла «Meme Collector.app»)
А вот какие — две штуки:
Посмотрим первый — Info.plist:
Ничего интересного, какая-то общая информация. Ладно. Ну-ка, а второй:
Вернёмся к симулятору. Уберём наше приложение из оперативной памяти (как говорят, «из многозадачности»).
Сочетание клавиш ⇧⌘H в симуляторе iOS соответствует нажатию кнопки Home. Нажмите это сочетание дважды, чтобы показать экран многозадачности, и смахните Meme Collector в никуда вверх.
Кажется, он не очень доволен, что его смахивают:
В дальнейшем, когда я буду говорить «перезапустите приложение», я буду иметь в виду именно эту операцию.
Снова запустите приложение. 1234 виртуальных тугриков в вашем распоряжении!
От переводчика: я ждал большей интриги. Не бывает так просто! Хоть свой тестовый проект пиши.
Пользовательские настройки: небезопасно!
Из терминала (мы по-прежнему находимся в Meme Collector.app, так?) откройте файл:
Несложное упражнение для вас: используя методы, о которых говорилось выше, модифицируйте NSUserDefaults так, чтобы получить кучу мемов из серии «Y U No …» бесплатно. Даже если вы уже обо всём догадались, советую сделать это для закрепления.
Но ведь злоумышленники могут получить доступ к plist-файлам, даже когда iOS-девайс заблокирован — так где же безопасно хранить данные? Одно из решений — хранить данные в NSUserDefaults в зашифрованном виде. В этом случае (и не только. — Прим. К.О.) нужно проверять на валидность данные, читаемые оттуда.
Связка ключей: лучшие рецепты
Связка ключей «повышает ставки» для хакера. Злоумышленники не смогут ничего стянуть, если устройство заблокировано.
Тем не менее, не стоит полностью полагаться на одну только Связку ключей! И вот почему. Связку ключей поддерживает Apple. (Ну вы уже всё поняли, да?) Информация в ней зашифрована паролем пользователя, который обычно является простым 4-значным цифровым кодом. А это значит, что атака брутфорсом займёт минут двадцать. Узнав пароль, легко сдампить всю связку ключей.
Что же делать? Некоторые общие рекомендации:
Сеть: тестирование на проникновение
Ещё хакеры любят наблюдать, как приложение взаимодействует с сетью. Самый тупой способ увидеть, происходит ли какая-то работа с сетью на устройстве, это поискать URL’ы в бинарнике.
Находясь в папке бандла (Meme Collector.app), наберите в терминале:
Стой, куда столько! Команда strings идёт по разделам бинарника и выводит все элементы данных, похожие на строки. Отфильтруем шум:
А, ну вот, одна строка:
Похоже, в какой-то момент приложение обращается к генератору мемов по этому урлу. Будучи хакером, вы бы хотели исследовать это дело дальше, изучив сетевой трафик приложения. Для этого нам понадобится сетевой монитор, перехватывающий все входящие и исходящие запросы.
Charles, упомянутый в начале статьи — хороший вариант для такого исследования. Скачайте его, если ещё не сделали это. Установите и запустите.
Проверьте, что Charles ловит сетевое взаимодействие с симулятора iOS (путём запуска «Карт», или в Safari набрать урл). Вы увидите, как в Charles побегут сетевые запросы. Если этого не произошло, убедитесь, что в меню Proxy > Mac OS X Proxy галочка установлена.
Выберите вкладку Response и затем внизу JSON. Ответ сервера, расшифрованный из JSON, представлен в виде красивой таблички:
Мы видим здесь множество строк вида «ключ-значение»: заголовок ( displayName ), описание ( description ), URL картинки ( imageUrl ) — в общем, некая информация по данному типу мемов «Four Bachelor Frog» из GET-параметра.
Похоже на то, что мы видели в приложении, правда? Двум другим картинкам в этот раз повезло меньше, они так и не дождались ответа от сервера (Charles сообщает об этом на вкладке Overview) и поэтому не отобразились в приложении.
При повторном запуске картинки могут браться из кэша симулятора, Charles лб этом не знает. Очистите кэш и перезапустите приложение.
Итак, с определённой долей вероятности делаем вывод: приложение берёт мемы с данного API и представляет их в виде платного контента. А что если попытаться изменить URL с целью приобрести какой-то новый контент, кроме этих трёх мемов? Непохоже, что тут есть проверка, действительно ли приложение получает с сервера то, что ожидал разработчик!
Вам уже надоели эти три мема? Ну-ка попробуем, можно ли отобразить и «купить» что-то новое, скажем, «Success Kid».
Выберите в меню Charles: Tools > Rewrite. Эта функция позволяет перехватывать входящие/исходящие запросы и модифицировать их по тем правилам, которые вы установите. Включите галочку Enable Rewrite. Правила группируются в «наборы» (Sets). Под списком Sets нажмите Add для добавления нового набора правил. По желанию, переименуйте (Name). Мы создали набор правил, но он пока пустой. Давайте добавим правило — в разделе Rules есть кнопка Add, нажмите её.
Открылось окно Rewrite Rule. Измените Type на «Modify Query Param» («Изменить параметр запроса») и заполните два поля:
Нажмите OK, OK. Перезапустите приложение… Success! Мы можем покупать контент, который ранее был недоступен.
Интересно: для этого нового мема указана конкретная цена. Откуда? Приложение должно было как-то определить стоимость, исходя из JSON-ответа.
Откройте вкладку Response и посмотрите на JSON, который возвращает сервер. Что может определить стоимость цены?
Попробуйте найти JSON-ключи, которые могут определить стоимость мема в приложении. Может быть, это generatorID, totalVotesScore, instancesCount, templatesCount или ranking. В качестве упражнения для вас: найдите тот ключ, который влияет на стоимость мема.
Теперь перезапустите приложение. Как только нам придёт ответ с сервера, сработает точка останова (breakpoint). Когда это произойдёт, щелкните на вкладке Edit Response, внизу выберите JSON:
Здесь вы можете вручную модифицировать JSON-ответ, который пойдёт в приложение. Поиграйтесь с этими параметрами и попробуйте определить, какие ключи влияют на цену, отображаемую в приложении. Изменив JSON-ответ, нажмите Execute (выполнить) для отправки ответа. Приложение делает три запроса к API, поэтому вам понадобится нажать Execute трижды.
Важно: действуйте быстро! AFNetworking имеет таймаут 30 секунд. Если вы перехватили ответ, но не успели внести изменения, AFNetworking вернёт ошибку таймаута запроса и выполнит соответствующий обработчик в коде (который в данном случае не делает ничего). Если у вас вышло время, перезапустите приложение и попробуйте снова.
Что дальше?
Вы открыли в себе хакерские способности и выполнили простейшие тесты на проникновение на примере файловой системы и сетевого взаимодействия конкретного приложения. Вы победили простые plist’ы и даже можете модифицировать ответы сервера.
Возможно, эти знания повысят безопасность вашего iOS-приложения… чуть-чуть. В следующей части мы углубимся гораздо дальше в недры приложения, будем изменять его функционал! А пока вы ждёте, когда я выложу перевод (до следующей пятницы), можно много чего попробовать на тему хранения данных в приложении:
Без джейлбрейка? Да ну?
Замечания по поводу перевода или неработающих примеров можно отправлять на почту dev @ x128.ru.
Как взломать iOS приложение для iPhone, iPad и iPod
В этой статье я расскажу о взломе приложений для iPhone и прочих iOS устройств. Для достижения этой цели будут описаны 2 способа с пошаговыми инструкциями и сопровождаемые скриншотами. Данная процедура взлома iOS приложений будет интересна тем, кто хотел бы делиться купленными приложениями.
1. Crackulous: простая программа для взлома iOS-приложений
Данная программа довольно-таки проста в использовании и имеет удобный графический интерфейс. Ее можно легко установить из Cydia. Кому непонятно, для использования приложения Crackolous необходим jailbreak. Взлом iOS приложений производится одним движением, в результате становится доступным для установки на любое другое устройство Apple. Перейдем непосредственно к пошаговой инструкции по установке и использованию приложения Crackulous:
Добавьте репозиторий Hackulo.us. Используйте путь «Sources» — «Edit» — «Add» / «Источники» — «Изменить» — «Добавить» и введите «cydia.hackulo.us»). Теперь найдите и установите Crackulous.
Откройте приложение Crackulous и используя закладку «Applications» выберите необходимое приложение или игру, которую хотите взломать и нажмите на него.
Непосредственно процесс взлома приложения происходит в закладке «Cracking». В поле «Cracking» отображаются приложения, которые еще взламываются, а в «IPAs» завершенные.
Используйте любой файловый менеджер (к примеру, iFunBox). Найдите взломанное приложение по следующему пути: var/root/Documents/Cracked. Приложение взломано и готово к использованию.
Согласитесь, очень простой вариант, но не без подводных камней. Случается, что Crackulous выдает ошибку:
Давайте перейдем к варианту решения данной ошибки взлома, как ко 2-ому способу взлома приложений iOS. Решение ошибки уступает простоте использования Crackolous, но половина, описанных ниже операций не требует повторных действий.
Подготовка iPhone к взлому приложений iOS
Установите «MobileTerminal» из стандартного репозитория «BigBoss». Обратите внимание в необходимости именно того, что имеет название без пробела.
Удалите «GNU Debugger», если он имеет место в системе. Вполне вероятно, что он скрыт. В этом случае выберите режим «Expert» в разделе «Packages».
Теперь установите скрипт «PoedCrackMod» из репозитория http://jcjeff.fav.cc/.
Последним подготовительным шагом вам необходимо создать папку «Cracked» в директории /var/mobile/Documents/. Проделать эту процедуру можно любым файловым менеджером (например, iFile).
Взлом iOS приложений 2-ым способом (для пользователей iOS 5+)
Завершив подготовку, давайте перейдем к работе со скриптом
Откройте MobileTerminal, который вы установили ранее.
Последующие шаги выполняются для упрощения процесса ввода объемных по содержанию команд.
Шаг 2.
Нажмите кнопку с изображением кнопки «i», далее нажмите на 1 пункт «Shortcut Menu».
Добавьте новый пункт, нажав на кнопку с изображением плюса.
Укажите название «горячей» клавиши (например «Crack!»). Затем наберите саму команду
Внимание! Соблюдайте реестр и пробелы в указанных местах!
Сохраните и перейдите обратно к MobileTerminal. Нажмите на кнопку в виде синей стрелки напротив кнопки настроек и выберите свою команду, в данном случае «Crack!». Вы можете убедиться, что она сразу появилась в терминале. Теперь вам больше не надо запоминать эту команду и вводить ее каждый раз.
Нажмите «return», тем самым выполнив команду, в результате должен появится список приложений, установленных на вашем смартфоне.
Взлом iOS приложений 2-ым способом (для пользователей iOS 4+)
Отдельного внимания заслуживают пользователи iOS 4 версии, потому как у них возникает ошибка.
P.S. Решение ошибки взлома на iPhone 5+
Cразу после запуска введите команду
В результате произведенных действий все команды выполняются от имени root пользователя и вы можете приступить ко взлому приложения.
Взлом и внедрение своего кода в чужое iOS-приложение
В жизни хакеры не так всесильны и эффектны, как в голливудских фильмах. Но это не значит, что iOS-разработчик может вообще не думать о безопасности своего приложения. Пусть оно и не хранит тайны Пентагона, взломать его всё равно могут хотя бы для того, чтобы получить платные функции бесплатно.
На нашей конференции Mobius разработчик Мурад Татаев рассказывал о взломе iOS-приложений — и о том, что разработчики могут делать для защиты от него. А теперь мы расшифровали этот доклад (видеозапись также прилагаем). Далее повествование идёт от лица спикера.
Мы не будем говорить о защите сетевого слоя — о SSL Pinning и тому подобном, а рассмотрим только взлом приложения. Будет теоретическая часть, где мы разберемся с некоторыми понятиями, и практическая, где применим полученные знания.
Начнем с теории
Взлом
В моем понимании взлом — это изменение поведения приложения в интересах хакера. То есть приложение работает не так, как изначально задумывал программист. В основном поведение меняется в тех частях, что связаны с получением чего-то, обычно за деньги — хакер хочет получить это бесплатно.
Относительная безопасность
Относительная безопасность означает, что затраты на атаку превышают полученную в результате выгоду. Допустим, у вас есть погодное приложение, в котором нет внутренних покупок. Вы пользуетесь открытым API, вам нет смысла париться о безопасности. И в результате взлома вы ничего не потеряете.
Но если вдруг у вас что-то серьезнее, например, фоторедактор, в котором через встроенные покупки можно открыть дополнительные фильтры, то стоит задуматься о безопасности.
Нужно понимать, что абсолютной безопасности вы не добьетесь. Вы можете добиться некоторой «лучшей обезопашенности» по сравнению с тем, что было раньше.
Почему важно защищать приложение?
Чтобы это понять, нужно увидеть в этом смысл. И он в основном экономический, реже — репутационный.
Для примера возьмем YouTube Tools — твик для отключения рекламы в приложении YouTube. В чем проблема: из-за того, что вы не смотрите рекламу, YouTube недополучает денег. Разработчики YouTube знают об этом и часто борются с различными твиками.
Еще один пример — обход платного скачивания Minecraft. В этом случае особенно не защитишься, потому что пользователь скачает приложение, расшифрует его, выложит файл, и его скачают другие.
Но в двух предыдущих вариантах (YouTube и Plague Inc.) есть способы бороться с хакерами, причем их довольно много.
Как защищаться?
Это главный вопрос. Есть несколько вариантов, которые я знаю:
Совет: проверяйте, нет ли в интернете вашего взломанного приложения.
Проверка на джейлбрейк
Плюсы: легко и дешево использовать (достаточно скопировать и вставить код).
Минусы: во-первых, это очень легко пропатчить.
Во-вторых, страдают некоторые мирные пользователи, которые могли поставить джейлбрейк не чтобы получить что-то ваше бесплатно, а чтобы пользоваться различными другими твиками.
Есть и обратная сторона — джейлбрейк используется все реже, но есть и те, кто по-прежнему ставят его.
Проверка на дебаггер
Плюсы: легко использовать, сложнее патчить.
Это хорошо работает с отложенными ошибками. Если вы узнали, что пользователь запустил ваше приложение с подключенным дебаггером или у него джейлбрейк и так далее, вы можете конкретно в каких-то критичных местах не давать ему проходить дальше. Такую ошибку нужно показывать не сразу, а делать это позже, чтобы код проверки не был в очевидном месте.
Минусы: это тоже патчится.
Примерный код проверки выглядит так:
Мы создаем структуру для информации о процессе, задаем размер этой структуры и с помощью утилиты systemctl пытаемся запросить флаги для текущего процесса. Если у нас получилось запросить их — идем дальше и проверяем, активен ли флаг P_TRACED. При помощи этого флага производится дебаггинг в iOS.
Если флаг стоит не в null, то нас дебажат.
Обфускация кода
Есть различные обфускаторы, один из популярных, насколько я понял по GitHub — это SwiftShield.
Плюсы: код превращается в лабиринт, в нем вообще не разберешься. Особенно классные обфускаторы создают дополнительные методы, мусор, чтобы запутать хакера. Насчет Swift не уверен, но в C#, Java и Kotlin есть такие.
Минусы: иногда этот лабиринт сказывается и на вас. И еще крэш-логи приходится каждый раз расшифровывать.
На скриншоте — крэш-лог одного из приложений.
Над зеленой полосой — крэш-лог до расшифровки, ниже — расшифрованный крэш-лог. Крэш-лог нужно расшифровывать через утилиту, которая идет вместе со SwiftShield. Это можно автоматизировать: засунуть в CI дополнительный job, чтобы подтягивать все крэш-логи, прогонять их через утилиту и что-то делать с ними дальше. Но это дополнительная работа.
Еще один большой минус — нет готовых решений, годных для энтерпрайза. Они опенсорсные. Это не плохо, но нужно быть осторожным, подтягивая что-то опенсорсное в ваш проект, особенно если он связан с безопасностью и обфускацией.
Я за свою практику не сталкивался с тем, чтобы кто-то в iOS пользовался обфускатором кода, поэтому это очень редкая практика.
Strip Swift Symbols
Плюсы: легко и дешево использовать, удаляется часть информации о Swift-классах. И это включено по умолчанию, то есть Xcode думает о вашей безопасности.
Минусы: информацию о классе можно найти другим способом.
Зачем нужно включать Strip Swift Symbols?
Допустим, у нас есть стандартный класс ViewController, label, viewDidLoad и так далее. Прошу обратить особенное внимание на статичную функцию buildScreen, о ней мы еще поговорим.
Если вы оставили Swift Symbols и после этого прогнали бинарник вашего приложения через специальную утилиту dsdump, вот что появится в логе:
Ниже можно увидеть, что есть некоторые свифтовые методы, и по названиям методов и переменных вы можете примерно понять, что здесь происходит и важен ли для вас этот класс. Что самое интересное, здесь нет статического метода buildScreen. Статические методы находятся в другом месте.
Вот что будет, если включить эту функцию: как вы видите, данных о свифтовых методах просто нет. Есть все, что связано с Objective-C и бриджингом для Objective-C.
Валидация покупок на сервере
Это очень хорошая практика, которой придерживаются не все. Среди топ-100 приложений я находил немало тех, у которых валидация все еще производится на девайсе, и при помощи одного твика можно обойти валидацию (подмена ответа сервера).
Плюсы: безопасность.
Минусы: вам придется покупать хостинг.
А если вы будете валидировать на клиенте?
Плюс: вам не нужен сервер.
Минус: потенциальная потеря денег. Твик LocaliAPStore будет вашим худшим врагом.
В качестве примера могу привести одно приложение, связанное с фоторедактированием. Название я, к сожалению, не могу сказать. Это приложение как раз не использует валидацию покупок на сервере. Приложение классное, но при помощи одного твика вы можете получить всё бесплатно.
Еще есть одна RPG-игра, она тоже находится в топах, там тоже валидация покупок на девайсе. Даже у известного раннера про подземки и бег с поездами такая же проблема — валидация идет на девайсе.
Инструменты — чем я пользуюсь каждый день
Filza — файловый менеджер, в котором скрыто очень много функций. С его помощью вы можете поднять сервер, FileDAV и обмениваться файлами с компьютером.
Unc0ver — это джейлбрейк, которым я пользуюсь. Он поддерживает версии вплоть до iOS 13.5.
Но с iOS 13.5 я бы посоветовал быть осторожней, потому что встроенный браузер в приложении, Safari View Controller, работает плохо. Лично у меня, когда я открываю ссылки, появляется окно внутреннего браузера (Safari View Controller), которое абсолютно пустое и ничего не грузит.
Cydia — это менеджер пакетов для взломанных устройств.
Наверное, некоторые из вас слышали, что Cydia — всё, закрыта, но нет, она поддерживается и вполне живет. Здесь есть куча разных твиков. Мы будем использовать Cydia в основном для того, чтобы устанавливать различные инструменты на устройство. С Cydia вы можете скачать ту же самую Filza.
NewTerm — это мобильный терминал. Он тоже доступен из Cydia и тоже полезная штука.
FLEXing — твик для поверхностного анализа приложения на устройстве. При помощи него можно посмотреть интернет-трафик, ваши файлы и тому подобное. Снифер трафика обходит SSL Pinning.
Я так проверял трафик в Instagram, а там есть SSL Pinning,
Можно посмотреть объекты в куче, которые есть сейчас, и вызвать различные методы в этих объектах. Есть общий список классов для приложения, можно поверхностно посмотреть, что там есть. Можно посмотреть UserDefaults и, неожиданно, Keychain.
Keychain — это, грубо говоря, тот же самый UserDefaults, только зашифрованный вашим паролем, то есть пин-кодом от вашего устройства. Если вы введете пин-код, Keychain разблокируется, и все, что там лежит, можно посмотреть. Так что я бы вам советовал не хранить ничего незашифрованного в Keychain, потому что до этого можно добраться и что-то поменять.
Как делать не надо
В AppDelegate есть строка isUnlocked:
То есть разработчик добавил в AppDelegate переменную, с помощью которой он смотрит, куплено приложение или нет.
Естественно, эта переменная легко меняется: вы жмете кнопку i, дергаете свитч, нажимаете «ОК». Поменяли переменную, закрыли меню флексинга, и у вас полностью «купленное» приложение.
Ghidra
Классная штука, дизассемблер от АНБ США, здесь можно вставить шутку про слежку от спецслужб.
Переходим к практике
Мы будем практиковаться на тестовом проекте.
Как достать расшифрованное приложение?
Есть ограничения — не дампятся extensions. Но за все время, что я этим пользовался, мне extensions и не были нужны.
Обход проверки на джейлбрейк
Патчим бинарник. Тот проект, что вы скачали ранее, выглядит так: простой белый экран, на нем — label с текстом: либо Hacked, либо Safe and sound в зависимости от того, джейлбрейкнуто устройство или нет.
Если все сделали правильно, это будет выглядеть примерно так:
Как найти необходимый участок кода?
Так как у нас код не обфусцирован, нужно либо вручную, не давая методам слишком очевидные имена, либо утилитами обфусцировать код.
При помощи поиска ищем слово jail в настройках. Найдется пара методов. И если вы нажмете на один из них, как можно увидеть чуть выше, курсор прыгнет в нужную область памяти.
Патчим инструкцию
Здесь вы видите инструкцию bl (branch with link) — это по сути прыжок на функцию, которая ожидает, что из этой функции что-то вернется в регистре w0. Если мы знаем, в какой регистр вернется значение, мы можем выполнить команду mov (присваивание).
То есть в регистр w0 записывается как раз то, что возвращается с метода. Мы записываем 0 (то есть false), экспортируем бинарник. Так как мы не трогали остальные фреймворки, нам нужен только бинарник.
После этого все подписываем, собираем и устанавливаем на устройство.
Готово — вы пропатчили приложение.
Подпись и установка приложения
Необходимые предварительные требования:
Копируем необходимые файлы
Создаем Adhoc Provisioning Profile и копируем его в папку с приложением. Дальше выполняем код:
В итоге мы получим entitlements.plist, который нам нужен. Profile.plist уже не нужен. Система безопасности iOS построена вокруг этих entitlements.
security — утилита macOS, с помощью которой можно работать с сертификатами, паролями, keychains и всем, что связано с безопасностью.
После этого копируем Adhoc Provisioning Profile в контейнер приложения (папку Payload/*.app) и переименовываем его в embedded.mobileprovision. Это обязательно!
Находим ключ для подписи
Этот код ищет сертификат, при помощи которого можно подписать приложение. В моем случае я выбрал iPhone Distribution, можно выбрать Developer, разницы я не заметил. Она может возникнуть, когда вы будете пытаться залить это все в App Store. Но в локальном тесте разницы нет.
Подписываем файлы
Это самое интересное. Вводим codesign, не забываем подписывать фреймворки. В моем случае там лежали только dylib, если лежат еще и фреймворки — обговорим этот кейс позже.
Не забывайте сначала подписать основной бинарник, а потом все приложение. В таком порядке у меня все работало отлично.
И устанавливаем. Не забывайте, чтобы устройство было подключенным через кабель, иначе работать не будет.
Cтавим через ideviceinstaller, а не Xcode — ideviceinstaller пишет логи в консоль, и вы сможете понять, на каком шаге допустили ошибку. Это довольно сильно облегчает дебаг.
Инъекция фреймворков и подмена реализации методов
Дальше начинается самое интересное, то есть настоящий взлом. Необходимые инструменты:
Потренируемся!
Советую всем начинать с простого и только потом бежать взламывать пентагоны.
Приложение называется Mobius Conf. У вас есть 300 монет, можно добавить монеты, то есть их купить, но мы так делать не будем, либо можно что-то купить внутри приложения за 200 монет.
Скорее всего, большинству из вас код будет непонятен. Метод вызывается в момент. когда загружается ваш фреймворк. Стоит учитывать, что именно в этот момент приложения еще нет, оно только грузится.
Здесь нельзя сразу пытаться что-то менять. Именно поэтому здесь прописан dispatch_after. Через три секунды на экране появится алерт с текстом вроде «Вы это сделали, классно». Если вы скопировали, вставили, все заработало — прекрасно, это первый шаг в сторону взлома.
Поиграем с кодом
Cydia Substrate — это такой фреймворк для подмены реализации методов, другими словами, для хукания методов. Есть метод с изначальной реализацией, которую задумал программист, и есть ваш метод. Вы берете и подменяете эти методы. На этом фреймворке держатся все твики, которые лежат в Cydia.
Попробуем вызвать какую-нибудь функцию.
В навигаторе Xcode откройте папку Products. Вы можете открыть файл MobiusStep2.app в Finder, перейти в папку app через терминал, войти в app-контейнер и с помощью утилиты dsdump принтануть все символы, которые есть в приложении.
Все статичные методы в приложении тоже реализованы в виде символов.
Вводите ViewDidLoad или то, что вам интересно. Здесь есть два метода, я выбрал второй, вы можете выбрать первый — по сути, это одно и то же.
Копируете всю строку, в Xcode удаляете весь предыдущий код и вводите команду MSFindSymbol.
Что такое MS? Изначально CydiaSubstate называлась MobileSubstate, и MS — дань уважения этому. MSFindSymbol делает то же, что и dsdump — идет поиск символа, копируется отступ по памяти, дополнительные данные. Всё это нужно для того, чтобы позже можно было что-то менять по этому символу.
Можно что-то вызвать по этому символу:
Но имейте в виду, что в этом методе могут вызываться различные переменные, которые еще не инициализированы. И возможно, приложение будет просто крашиться. Поэтому будьте осторожны, и лучше всего через Ghidra заранее проверять метод, который вы хотите вызвать: посмотреть в интерпретаторе, не идут ли вызовы в какие-то локальные переменные, которые еще не инициализированы, и так далее.
Если вы так вызовете символ в этом проекте, вы увидите, что принтанется viewDidLoad. Из-за того, что вы сами вызвали viewDidLoad, и после этого вызвался «натуральный» метод, у вас в консоли продублируется текст viewDidLoad.
Давайте вызовем свой код после viewDidLoad.
Это уже что-то более боевое и интересное. Из предыдущего кода остается MSFindSymbol, но только вызов MSFindSymbol заменяется на MSHookFunction. Здесь оригинальный метод заменяется на засвизленный, то есть на наш.
В нашем методе мы сначала вызываем оригинальную имплементацию в виде Load, и после него идет наш код. Ничего оригинального не стал придумывать, просто через 2 секунды отображаю алерт.
Как насчет бесконечности денег?
Если вы будете бродить по символам, найдете интересный символ PurchaseManager spend. Из названия понятно, что этот метод будет вызван, если что-то нужно потратить, например, деньги. И этот метод можно захукать.
С помощью Ghidra можно понять и проверить, что этот метод на входе принимает аргумент в виде количества денег, и просто подменить оригинальную реализацию своей.
Разница в том, что мы не учитываем количество денег, которое потратил пользователь, — всегда передаем 1. Каждый раз, когда вы нажимаете кнопку покупки, единичка будет уходить. Можно передавать 0, и тогда у вас будет бесконечное количество денег (они не будут тратиться).
Потренировались? Будем инжектить в реальное приложение.
Здесь есть Foundation, Objective-C, UIKit, SwiftCore и так далее.
При помощи optool можно добавить свою дополнительную строку. Вводим код:
Добавится новая строка. Это можно проверить, вызвав команду:
Вы увидите, что в конце добавлена новая строка на загрузку нового фреймворка. Обязательно после фреймворка написать / и путь до бинарника, иначе ничего не подгрузится и не будет работать.
Не забудьте подписать фреймворк!
Не забудьте скопировать фреймворк в папку с фреймворками — та строка, что мы писали, магическим образом не будет искать по всему проекту — только в папке Frameworks.
Можно объединить все в один shell-файл, чтобы не вводить каждый раз несколько команд. Можно добавить еще одну команду для подписи сразу всех фреймворков.
Вы заинжектили свой фреймворк и свой код в чужое приложение.
Но! Хукать свифтовые методы можно только на взломанном устройстве.
Если хотите хукать не только на взломанных устройствах и карма смотрит на вас лицом, то вам повезет, и то приложение, которое вы будете исследовать, будет на Objective-C.
Это еще одна причина, почему я говорил, что писать надо на Swift. Вы сейчас увидите, почему не следует писать на Objective-С что-то безопасное.
Это приложение MobiusStep3. Здесь кнопка добавления денег пропала, есть только кнопка «Потратить». Наша цель — иметь бесконечное количество монет. В этом нам поможет Objective-C Runtime и тот же свизлинг методов.
Подготовка проекта
Их немного, и если присмотреться, можно заметить уязвимый метод spend. Мы его взламывали ранее, и он может принести потенциальные проблемы.
Будем свизлить как раз-таки его, здесь классический свизлинг методов. Находим класс по имени, находим селектор по имени и подменяем реализацию оригинального метода на неоригинальный.
Не забываем сохранять ссылку на предыдущую (оригинальную) реализацию. Можно заметить строку с переменной originalImplementation, так мы держим ссылку на оригинальную имплементацию. IMP — это сишная структура, просто так IMP-структуры не вызвать, приходится их кастить.
Внизу видно, как мы их закастили через swizzled_spend. id, SEL — это обязательно. Наконец, вы можете увидеть int в коде, который кастим. На следующей строке вызываем этот метод и передаем 0 или 1. Единица удобна для дебага.
Все работает без мам, пап, кредитов и Cydia Substrate. Причина — особенность гипердинамичного Objective-C Runtime, где связывание с методами происходит как можно позже.
Резюмируем
И помните — абсолютной безопасности не существует. Но можно сделать безопаснее, чем было раньше.
Если вам захочется обсудить с Мурадом его доклад, напишите ему:
Если вы дочитали досюда и вы не злонамеренный хакер (фу таким быть) — тогда, скорее всего, вы мобильный разработчик. Тогда обращаем ваше внимание, что следующий Mobius пройдет 22-25 ноября, и там будет много новых докладов. Хакерский колорит в их случае не обещаем, а вот актуальность для мобильных разработчиков — вполне.