- PVSM.RU - https://www.pvsm.ru -

Ломаем iOS-приложение. Часть 1

Вы хорошо поработали, и вот ваше приложение в App Store!

  • Храните учётные записи юзеров?
  • Используете встроенные покупки?
  • Не хотите показывать своё ноу-хау?

Повод задуматься о безопасности кода и данных! Мы будем искать уязвимости в тестовом приложении. В этой статье поговорим о безопасности данных, а в следующей — перейдём к коду.

Disclaimer

Цель данного урока — не сделать вас хакером, а показать, как злоумышленники могут обвести вас вокруг пальца. В статье пропущена кое-какая инфа, необходимая для взлома реального приложения на девайсе. Будем мучить симулятор (кстати, это вроде бы даже законно[citation needed]).

Disclaimer от переводчика: из оригинального текста убрано много «воды» и отсылок к Голливуду (и так длинно). Добавлен ряд ключевых пояснений.

Итак

Ни одно приложение не является безопасным! Если кто-то действительно захочет найти у вас уязвимости, то он их найдёт. Нет гарантированного способа предотвратить атаку. Разве что, не выпускать приложение. Но есть отличные способы помешать взломщикам. (По мнению автора, им надоест, и они пойдут спать искать более лёгкую добычу, ага. — Прим. пер.)

Перед тем, как читать дальше, вы должны примерно понимать, что такое терминал, а также Objective C и Cocoa (впрочем, особо много кода не будет).

Приступим

Нам понадобится:
1. Утилита class-dump-z [1];
2. Прокси для отладки по сети, например, Charles [2] (триал-версия отличается надоедливыми сообщениями и работает максимум 30 минут за 1 сеанс). В комментах к исходнику [3] статьи советуют альтернативу Чарльзу — Burpsuite [4].

Чтобы вы творчески подошли к процессу, предлагаю вам сценарий. Представьте: вышло новое приложение для айпада — «Собиратель мемов» (Meme Collector). Всем нравится. Но вам шепнули на ухо, что встроенные покупки вытянут из вас значительную сумму денег.

Ломаем iOS приложение. Часть 1

В общем, вы задумали получить платный контент (мемы) бесплатно. Есть несколько направлений, куда можно двигаться, мы поговорим о них — и о соответствующих методах защиты.

Небольшое упрощение

Из-за длины этого урока мы изначально допустили некоторые упрощения в тестовом проекте. Например, «покупка» игровой валюты представляет из себя не настоящий in-app purchase, а фэйковый запрос к StoreKit (всё происходит локально на девайсе).

Что к чему? «Карта» приложения (application mapping)

Взглянем на приложение с высоты птичьего полёта! Что оно делает, с точки зрения пользователя? Какова его основная структура?

Откройте проект Meme Collector [5] в своей любимой IDE или в Xcode (не реклама).

Ломаем iOS приложение. Часть 1

Мы будем запускать приложение в конфигурации Release.
Xcode: Product > Scheme > Edit scheme… (⌘<) — слева выбрать Run…, справа вкладка Info > Build Configuration: Release.
AppCode: Run > Edit configurations… > Configuration: Release.

Запустите приложение на симуляторе iPad (⌘R). А теперь забудьте, что у вас есть исходники, вы — юзер. Откроется одно из двух:
Ломаем iOS приложение. Часть 1

У вас вариант слева?

Это хабраэффект или проблема с соединением. Мемы берутся с API memegenerator.net [6] — проверьте, что этот урл выдаёт {"success":true,"result":[список мемов]}. Во время перевода статьи у них были проблемы с сервером. Если есть желание избавить проект от зависимости от данного API, велкам на гитхаб.

Этот странный интерфейс позволяет «купить» мем по тапу на него, а также показывает число покупок данного мема и остаток денег на вашем счёте. От переводчика: нажав кнопку «Purchase Currency», я реально задумался: а не вводил ли я Apple ID на симуляторе?

Ломаем iOS приложение. Часть 1

…но вспомнил, что у меня к US-аккаунту не привязана кредитка. :) Русский бы сказал цену в рублях.

В общем, всё просто. Есть «игровая валюта», и вы (типа взломщик) не хотите отдавать за неё реальные деньги. Наша цель — получить больше мемов, не нажимая кнопку «Purchase Currency».

Мы примерно поняли, что делает приложение, давайте заглянем глубже. Что ещё мы можем узнать?

Упомянутая утилита class-dump-z отобразит нам все объявления (declarations), которые она сможет достать из исполняемого файла. Скачайте [1] последнюю версию утилиты (например, 0.2a), распакуйте архив. В терминале перейдите в папку class-dump-z_0.2a/mac_x86/. Там есть исполняемый файл class-dump-z, установите его, например, скопировав в /usr/bin/:

sudo cp class-dump-z /usr/bin/

Перейдите в папку симулятора iOS: (вместо 7.0.3 — ваша версия)

cd ~/Library/Application Support/iPhone Simulator/7.0.3/Applications/

Здесь лежат все приложения, которые вы запускали в симуляторе. Их там может быть много. Как найти Meme Collector?

Вариант 1. Если вы только что запускали Meme Collector, то он лежит в папке с самой новой датой модификации. Просто перейдите в неё:

cd `ls -tr | tail -1`
Это что за магия?

  • Команда ls выдаёт содержимое папки. Флаг "-tr" сортирует по времени: самая новая папка будет последней в списке.
  • Весь этот список поступает на вход команды tail. Она берёт некоторый объём данных с конца. В данном случае — ровно одну строчку (флаг "-n 1" или просто "-1").
  • Далее команда cd переходит в эту самую новую папку.

Вариант 2. Взять и найти:

find . -name "Meme Collector"

В моём случае папка называется 9A72F266-8851-4A25-84E4-9CF8EFF95CD4 — далее будем называть её просто «папкой приложения». В ней лежит:

  • Meme Collector.app — главный бандл (main application bundle)
  • ещё что-то :)

Бандл — это папка (именно папка, да, с расширением .app), в которой есть один или несколько исполняемых файлов плюс ресурсы к ним (картинки, звуки, цифровая подпись, в общем, что угодно, даже другие бандлы… read more [7]). Перейдём в папку основного бандла:

cd Meme Collector.app

Тут есть исполняемый файл, который так и называется: Meme Collector (без расширения). Посмотрим, на какие фреймворки (frameworks) и общие библиотеки (shared libraries) имеются в нём ссылки. Нам поможет стандартная утилита otool:

otool -L "Meme Collector"

И вот что видим:

Meme Collector:
	/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 615.0.0)
	/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 51.0.0)
	/System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.8.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 2903.23.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1047.22.0)
	/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 600.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
	/usr/lib/libSystem.dylib (compatibility version 1.0.0, current version 111.0.0)

Мм, интересно, приложение использует фреймворк Store Kit [8] — встроенные покупки? Ну-ка, идём дальше. Запускаем утилиту class-dump-z:

class-dump-z "Meme Collector" > ClassDump.txt

И откроем полученный файл в стандартном гуёвом редакторе:

open ClassDump.txt

Ломаем iOS приложение. Часть 1Ого! Хотя нет, по сравнению с примером из оригинальной статьи [9] (Xcode 4, iOS 6 SDK) появились неприятные моменты типа XXUnknownSuperclass, но всё же! Мы видим не только интерфейсную часть, но и объявления закрытых (private) методов, свойств, протоколов.

Изучение дампа классов серьёзного проекта — чаще всего утомительное занятие. Но оно может дать потрясающую картину внутреннего устройства приложения!

Итак, мой юный следопыт! Найдите-ка мне все синглтоны в приложении.

Подсказка

В сигнлтонах часто встречаются объявления методов класса [10] с ключевыми словами: manager, shared, store.

Если встретите интересный синглтон, изучите все его методы.
(Видимо, «интересный» = «похоже, имеющий отношение к логике приложения». — Прим. пер.)

Решение

Точно нашли? Посмотрите у себя внимательнее. Их там около четырёх штук.

Да, все.

  • AFNetworking
  • MemeManager — интересный синглтон! Он содержит:
    @property(retain, nonatomic) AFHTTPClient* client;
    @property(readonly, assign, nonatomic) NSMutableArray* memes;
    +(id)sharedManager;
    -(void)memePurchased:(int)purchased;
    -(void)getMemeInformation; // кстати, это private-метод
    
  • MoneyManager — тоже интересный синглтон:
    @property(readonly, assign, nonatomic) NSNumber* money;
    +(id)sharedManager;
    -(BOOL)saveState; // кстати, это private-метод
    -(void)loadState; // кстати, это private-метод
    -(BOOL)purchaseCurrency;
    -(BOOL)buyObject:(id)object;
    
  • SVProgressHUD

Взломщики часто делают то, что вы сейчас сделали — ищут определённые слова в дампе класса. Например, если они хотят узнать, есть ли в приложении логика, завязанная на джейлбрейк девайса, то поиск по словам 'jailbroken', 'security' и т.д. может дать быстрый ответ.

Как это предотвратить?

Есть две новости. Начну с хорошей.

Apple делает это за вас автоматически. Когда вы отправляете приложение в App Store, они шифруют ваши бинарники с использованием DRM-технологии под названием FairPlay [11]. Если вы сдампите class-dump-z'ом зашифрованный бинарник, то получите… тарабарщину.

Плохая новость: обойти эту защиту довольно легко! Дело на 10 минут (вручную), а ещё есть средства автоматизировать сей процесс. В общем, будьте уверены, ваше приложение расшифруют и увидят названия всех ваших классов, методов, протоколов и т.д.

Ломаем iOS приложение. Часть 1

Plist-файлы: уязвимы!

Мы кое-что узнали о приложении. Теперь поищем всё, что плохо лежит. Разработчикам свойственно ошибаться. Злоумышленникам свойственно использовать эти ошибки в своих целях.

Ошибки… Начнём с самых глупых! Например, как вам идея: использовать файл .plist для хранения критической информации? Взломщики всегда смотрят plist'ы: их легко просмотреть, а их изучение может дать ключ к внутренней логике приложения. (Plist = property list, текстовый файл с сериализованными объектами).

Посмотрим, какие plist'ы у нас есть?
(напомню, мы всё ещё находимся в папке бандла «Meme Collector.app»)

ls *.plist

А вот какие — две штуки:

Info.plist           MoneyDataStore.plist

Посмотрим первый — Info.plist:

plutil -p Info.plist

Результат:

{
  "DTSDKName" => "iphonesimulator7.0"
  "CFBundleName" => "Meme Collector"
  "CFBundleDevelopmentRegion" => "en"
  "CFBundleVersion" => "1.0"
  "DTPlatformName" => "iphonesimulator"
…и ещё куча всего…

Ничего интересного, какая-то общая информация. Ладно. Ну-ка, а второй:

plutil -p MoneyDataStore.plist

И видим:

{
  "userCurrency" => 108
}

Прикол! Этот .plist содержит ключ userCurrency с тем же значением, которое вы только что видели на экране симулятора. Значит ли это, что приложение хранит деньги в .plist'е? Есть только один способ узнать!

open MoneyDataStore.plist

Измените значение userCurrency, например, на 1234. Сохраните и закройте файл .plist.

Вернёмся к симулятору. Уберём наше приложение из оперативной памяти (как говорят, «из многозадачности»).

На всякий случай инструкция.

Сочетание клавиш ⇧⌘H в симуляторе iOS соответствует нажатию кнопки Home. Нажмите это сочетание дважды, чтобы показать экран многозадачности, и смахните Meme Collector в никуда вверх.

Кажется, он не очень доволен, что его смахивают:Ломаем iOS приложение. Часть 1

В дальнейшем, когда я буду говорить «перезапустите приложение», я буду иметь в виду именно эту операцию.

Снова запустите приложение. 1234 виртуальных тугриков в вашем распоряжении!
От переводчика: я ждал большей интриги. Не бывает так просто! Хоть свой тестовый проект пиши.

Пользовательские настройки: небезопасно!

Ну вы поняли? Хранить важную информацию в .plist — не самая лучшая идея. А теперь угадайте: что представляют из себя пользовательские настройки (NSUserDefaults)? Ага, тоже plist! Физически он лежит по адресу {App Directory}/Library/Preferences/{Bundle Identifier}.plist.

Это как раз то место, где разработчики часто ошибочно чувствуют себя в безопасности. Не только фрилансеры: крупные корпорации время от времени попадают в эту ловушку. Бесчисленное множество приложений хранят важные данные в NSUserDefaults. Посмотрим, что нам здесь приготовил Meme Collector?

Из терминала (мы по-прежнему находимся в Meme Collector.app, так?) откройте файл:

open ../Library/Preferences/com.selander.Meme-Collector.plist

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

Ломаем iOS приложение. Часть 1

Но ведь злоумышленники могут получить доступ к plist-файлам, даже когда iOS-девайс заблокирован — так где же безопасно хранить данные? Одно из решений — хранить данные в NSUserDefaults в зашифрованном виде. В этом случае (и не только. — Прим. К.О.) нужно проверять на валидность данные, читаемые оттуда.

Связка ключей: лучшие рецепты

Другое возможное решение — перенос важных данных из .plist'ов в Связку ключей iOS (Keychain). Как это сделать — написано, например, здесь [12].

Связка ключей «повышает ставки» для хакера. Злоумышленники не смогут ничего стянуть, если устройство заблокировано.

Тем не менее, не стоит полностью полагаться на одну только Связку ключей! И вот почему. Связку ключей поддерживает Apple. (Ну вы уже всё поняли, да?) Информация в ней зашифрована паролем пользователя, который обычно является простым 4-значным цифровым кодом. А это значит, что атака брутфорсом [13] займёт минут двадцать. Узнав пароль, легко сдампить всю связку ключей.

Что же делать? Некоторые общие рекомендации:

  • Шифруйте данные! Связка ключей вроде как безопасна, но это приоритетная цель для хакеров, поэтому её ломают в первую очередь. (Про джейлбрейкнутые устройства вообще нечего говорить — для них существуют утилиты, показывающие содержимое Связки ключей.) Усложните жизнь взломщикам хотя бы ненамного: шифруйте данные с помощью CommonCrypto API, который входит в состав стандартного Security Framework (пример [14]).
  • Не прописывайте ключ шифрования в приложении. Длинная строка в секции данных представляет потенциальный интерес для хакера. И вообще: если закрытый ключ прописан в приложении, злоумышленник может выложить его в сеть, скомпрометировав данные всех пользователей приложения! Обязательно генерировать уникальный ключ шифрования на каждом устройстве.
  • Контролируйте код! Конкретно — следите за возможностью хакера использовать ваш код в своих целях. Ваш метод шифрования/дешифрования может быть самым прекрасным решением. Но хакеры возьмут отладчик и применят ваш метод дешифрования к вашим же зашифрованным данным. Вы увидите это во второй части данного туториала (следующий пост).
  • Это точно нужно хранить? Раз злоумышленник может искать, модифицировать и выполнять ваши бинарники — просто спросите себя: эту информацию действительно нужно хранить на девайсе?

Сеть: тестирование на проникновение

Ещё хакеры любят наблюдать, как приложение взаимодействует с сетью. Самый тупой способ увидеть, происходит ли какая-то работа с сетью на устройстве, это поискать URL'ы в бинарнике.

Находясь в папке бандла (Meme Collector.app), наберите в терминале:

strings "Meme Collector"

Стой, куда столько! Команда strings идёт по разделам бинарника и выводит все элементы данных, похожие на строки. Отфильтруем шум:

strings "Meme Collector" | grep http

А, ну вот, одна строка:

http://version1.api.memegenerator.net/Generator_Select_ByUrlNameOrGeneratorID

Похоже, в какой-то момент приложение обращается к генератору мемов по этому урлу. Будучи хакером, вы бы хотели исследовать это дело дальше, изучив сетевой трафик приложения. Для этого нам понадобится сетевой монитор, перехватывающий все входящие и исходящие запросы.

Charles, упомянутый в начале статьи — хороший вариант для такого исследования. Скачайте [2] его, если ещё не сделали это. Установите и запустите.

Проверьте, что Charles ловит сетевое взаимодействие с симулятора iOS (путём запуска «Карт», или в Safari набрать урл). Вы увидите, как в Charles побегут сетевые запросы. Если этого не произошло, убедитесь, что в меню Proxy > Mac OS X Proxy галочка установлена.

Кстати, Charles отлично перехватывает SSL-трафик.

Мы не будем это делать, потому что не увидели HTTPS-урлов на выходе команды strings. Но этот шаг потребуется для других приложений, которые могут использовать HTTPS. В меню Proxy > Proxy Settings… > SSL нужно включить SSL-прокси и добавить домены, по которым требуется перехватывать (и расшифровывать) HTTPS-трафик. Пока вы это не сделаете, SSL будет выглядеть примерно так:

Ломаем iOS приложение. Часть 1

При работающем Charles перезапустите Meme Collector. После запуска вы должны увидеть три запроса к http://version1.api.memegenerator.net, нажав на треугольник слева от урла (см. ниже). Раскроются три запроса, отличающиеся GET-параметрами. Например, у первого один GET-параметр: urlName=Foul-Bachelor-Frog — это видно на вкладке Request.

Выберите вкладку Response и затем внизу JSON. Ответ сервера, расшифрованный из JSON, представлен в виде красивой таблички:

Ломаем iOS приложение. Часть 1

Мы видим здесь множество строк вида «ключ-значение»: заголовок (displayName), описание (description), URL картинки (imageUrl) — в общем, некая информация по данному типу мемов «Four Bachelor Frog» из GET-параметра.

Что происходит дальше? Приложение трижды делает одно и то же: HTTP-запрос по урлу картинки, пытается скачать её с cdn.memegenerator.co, получает 301-й редирект на cdn.memegenerator.net и качает оттуда.

Ломаем iOS приложение. Часть 1

Похоже на то, что мы видели в приложении, правда? Двум другим картинкам в этот раз повезло меньше, они так и не дождались ответа от сервера (Charles сообщает об этом на вкладке Overview) и поэтому не отобразились в приложении.

Ломаем iOS приложение. Часть 1

А я вообще не вижу, чтобы запрашивались картинки!

При повторном запуске картинки могут браться из кэша симулятора, Charles лб этом не знает. Очистите кэш и перезапустите приложение.

rm -R Library/Caches/

Итак, с определённой долей вероятности делаем вывод: приложение берёт мемы с данного API и представляет их в виде платного контента. А что если попытаться изменить URL с целью приобрести какой-то новый контент, кроме этих трёх мемов? Непохоже, что тут есть проверка, действительно ли приложение получает с сервера то, что ожидал разработчик!

Вам уже надоели эти три мема? Ну-ка попробуем, можно ли отобразить и «купить» что-то новое, скажем, «Success Kid».

Выберите в меню Charles: Tools > Rewrite. Эта функция позволяет перехватывать входящие/исходящие запросы и модифицировать их по тем правилам, которые вы установите. Включите галочку Enable Rewrite. Правила группируются в «наборы» (Sets). Под списком Sets нажмите Add для добавления нового набора правил. По желанию, переименуйте (Name). Мы создали набор правил, но он пока пустой. Давайте добавим правило — в разделе Rules есть кнопка Add, нажмите её.

Ломаем iOS приложение. Часть 1

Открылось окно Rewrite Rule. Измените Type на «Modify Query Param» («Изменить параметр запроса») и заполните два поля:

  • Match > Name: urlName
  • Replace > Value: success-kid

Ломаем iOS приложение. Часть 1

Нажмите OK, OK. Перезапустите приложение… Success! Мы можем покупать контент, который ранее был недоступен.

Ломаем iOS приложение. Часть 1

Интересно: для этого нового мема указана конкретная цена. Откуда? Приложение должно было как-то определить стоимость, исходя из JSON-ответа.

Откройте вкладку Response и посмотрите на JSON, который возвращает сервер. Что может определить стоимость цены?

Попробуйте найти JSON-ключи, которые могут определить стоимость мема в приложении. Может быть, это generatorID, totalVotesScore, instancesCount, templatesCount или ranking. В качестве упражнения для вас: найдите тот ключ, который влияет на стоимость мема.

Чтобы сделать это, перейдите к Proxy > Breakpoints. Нажмите Enable Breakpoints и нажмите Add, чтобы добавить новую точку останова. Появится окно Edit breakpoint, введите в нём следующие данные:

  • Protocol: http
  • Host: version1.api.memegenerator.net
  • опция Response включена

Ломаем iOS приложение. Часть 1

Теперь перезапустите приложение. Как только нам придёт ответ с сервера, сработает точка останова (breakpoint). Когда это произойдёт, щелкните на вкладке Edit Response, внизу выберите JSON:

Ломаем iOS приложение. Часть 1

Здесь вы можете вручную модифицировать JSON-ответ, который пойдёт в приложение. Поиграйтесь с этими параметрами и попробуйте определить, какие ключи влияют на цену, отображаемую в приложении. Изменив JSON-ответ, нажмите Execute (выполнить) для отправки ответа. Приложение делает три запроса к API, поэтому вам понадобится нажать Execute трижды.

Нашли, какой ключ влияет на цену?

Это ranking. Чем больше ranking, тем меньше цена.

Важно: действуйте быстро! AFNetworking имеет таймаут 30 секунд. Если вы перехватили ответ, но не успели внести изменения, AFNetworking вернёт ошибку таймаута запроса и выполнит соответствующий обработчик в коде (который в данном случае не делает ничего). Если у вас вышло время, перезапустите приложение и попробуйте снова.

Что дальше?

Вы открыли в себе хакерские способности и выполнили простейшие тесты на проникновение на примере файловой системы и сетевого взаимодействия конкретного приложения. Вы победили простые plist'ы и даже можете модифицировать ответы сервера.

Возможно, эти знания повысят безопасность вашего iOS-приложения… чуть-чуть. В следующей части мы углубимся гораздо дальше в недры приложения, будем изменять его функционал! А пока вы ждёте, когда я выложу перевод (до следующей пятницы), можно много чего попробовать на тему хранения данных в приложении:

  • Попробуйте такие средства, как iExplorer [15]. iExplorer позволяет изучить содержимое файлов, которые используются вашими реальными приложениями. Посмотрите, что они там хранят.

    Без джейлбрейка? Да ну?

    Серьёзно!

    Ломаем iOS приложение. Часть 1

  • Настройте SSL-прокси в Charles и проверьте его на реальных приложениях. Ну-ка, что отсылает это приложение с вашего девайса, тихо сидя в углу с милой UI'ыбкой? Вероятно, вы удивитесь. А наблюдение за сетевым взаимодействием приложений-конкурентов может обеспечить потрясающее понимание того, как они решили проблемы сетевого взаимодействия, схожие с вашими.
  • Подтяните свои знания по ассемблеру iOS (ARM). Автор советует этот туториал [16] (на английском). Следующая часть нашего урока будет гораздо более насыщенной! Готовьтесь.

Замечания по поводу перевода или неработающих примеров можно отправлять на почту dev@x128.ru.

Автор: x256

Источник [17]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/mobile-development/47820

Ссылки в тексте:

[1] class-dump-z: https://code.google.com/p/networkpx/wiki/class_dump_z

[2] Charles: http://www.charlesproxy.com/download/

[3] исходнику: http://www.raywenderlich.com/45645/ios-app-security-analysis-part-1#comments

[4] Burpsuite: http://highaltitudehacks.com/2013/08/20/ios-application-security-part-11-analyzing-network-traffic-over-http-slash-https/

[5] проект Meme Collector: https://github.com/x128/MemeCollector

[6] API memegenerator.net: http://version1.api.memegenerator.net/Generators_Select_ByNew

[7] read more: http://en.wikipedia.org/wiki/Application_bundle

[8] Store Kit: https://developer.apple.com/library/ios/documentation/StoreKit/Reference/StoreKit_Collection/_index.html

[9] оригинальной статьи: http://www.raywenderlich.com/45645/ios-app-security-analysis-part-1

[10] методов класса: http://en.wikipedia.org/wiki/Method_%28computer_programming%29#Class_methods

[11] FairPlay: http://en.wikipedia.org/wiki/FairPlay

[12] здесь: http://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1

[13] брутфорсом: http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%BB%D0%BD%D1%8B%D0%B9_%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%BE%D1%80

[14] пример: https://developer.apple.com/library/ios/samplecode/CryptoExercise/Introduction/Intro.html

[15] iExplorer: http://www.macroplant.com/iexplorer/

[16] этот туториал: http://www.raywenderlich.com/37181/ios-assembly-tutorial

[17] Источник: http://habrahabr.ru/post/199128/