Что такое objective c runtime
В данном посте я хочу обратиться к теме, о которой многие начинающие iPhone-разработчики Зачастую имеют смутное представление: Objective-C Runtime. Многие знают, что он существует, но каковы его вероятности и как его применять на практике?
Испробуем разобраться в базовых функциях этой библиотеки. Материал основан на лекциях, которые мы вCoalla используем для обучения работников.
Что такое Runtime?
Objective-C задумывался как надстройка над языком C, добавляющая к нему поддержку объектно-ориентированной парадигмы. Реально, с точки зрения синтаксиса, Objective-C — это довольно маленький комплект ключевых слов и руководящих конструкций над обыкновенным C. Именно Runtime, библиотека времени выполнения, предоставляет тот комплект функций, которые вдыхают в язык жизнь, реализуя его динамические вероятности и обеспечивая функционирование ООП.
Базовые конструкции данных
Функции и конструкции Runtime-библиотеки определены в нескольких заголовочных файлах: objc.h , runtime.h и message.h . Вначале обратимся к файлу objc.h и посмотрим, что представляет из себя объект с точки зрения Runtime:
Мы видим, что объект в процессе работы программы представлен обыкновенной C-конструкцией. Всякий Objective-C объект имеет ссылку на свой класс — так называемый isa-указатель. Думаю, все видели его при просмотре конструкции объектов во время отладки приложений. В свою очередь, класс также представляет из себя аналогичную конструкцию:
Класс в Objective-C — это полновесный объект и у него тоже присутствует isa-указатель на «класс класса», так называемый метакласс в терминах Objective-C. Подобно, С-конструкции определены и для других сущностей языка:
Функции Runtime-библиотеки
Помимо определения основных конструкций языка, библиотека включает в себя комплект функций, работающих с этими конструкциями. Их дозволено условно поделить на несколько групп (предназначение функций, как правило, видимо из их наименования):
- Манипулирование классами: class_addMethod , class_addIvar , class_replaceMethod
- Создание новых классов: class_allocateClassPair , class_registerClassPair
- Интроспекция: class_getName , class_getSuperclass , class_getInstanceVariable , class_getProperty , class_copyMethodList , class_copyIvarList , class_copyPropertyList
- Манипулирование объектами: objc_msgSend , objc_getClass , object_copy
- Работа с ассоциативными ссылками
Пример 1. Интроспекция объекта
Разглядим пример применения Runtime библиотеки. В одном из наших планов модель данных представляет собой plain old Objective-C объекты с некоторым комплектом свойств:
Для комфорта отладки хотелось бы, Дабы при итоге в лог печаталась информация о состоянии свойств объекта, а не что-то как бы . От того что модель данных довольно разветвленная, с огромным числом разных подклассов, неугодно писать для всякого класса обособленный способ description , в котором вручную собирать значения его свойств. На поддержка приходит Objective-C Runtime:
Способ, определенный в всеобщем суперклассе объектов модели, получает список всех свойств объекта с поддержкой функции class_copyPropertyList . После этого значения свойств собираются в NSDictionary , тот, что и применяется при построении строкового представления объекта. Данный алгорифм раработает только со свойствами, которые являются Objective-C объектами. Проверка типа осуществляется с применением функции property_getAttributes . Итог работы способа выглядит приблизительно так:
2013-05-04 15:54:01.992 Test[40675:11303] COConcreteObject: name = Foo;
quantity = 10;
title = bar;
>
Вызов objc_msgSent инициирует процесс поиска реализации способа, соответствующего селектору, переданному в функцию. Реализация способа ищется в так называемой таблице диспетчеризации класса. От того что данный процесс может быть довольно продолжительным, с всяким классом ассоциирован кеш способов. Позже первого вызова всякого способа, итог поиска его реализации будет закеширован в классе. Если реализация способа не обнаружена в самом классе, дальше поиск продолжается вверх по иерархии наследования — в суперклассах данного класса. Если же и при поиске по иерархии итог не достигнут, в дело вступает механизм динамического поиска — вызывается один из особых способов: resolveInstanceMethod либо resolveClassMethod . Переопределение этих способов — одна из последних вероятностей повлиять на Runtime:
Пример 2. Method Swizzling
Одна из особенностей категорий в Objective-C — способ, определенный в категории, всецело перекрывает способ базового класса. Изредка нам требуется не переопределить, а расширить функционал имеющегося способа. Пускай, скажем, по каким-то причинам нам хочется залогировать все добавления элементов в массив NSMutableArray . Стандартными средствами языка этого сделать не получится. Но мы можем применять прием под наименованием method swizzling:
Мы перегружаем способ load — это особый callback, тот, что, если он определен в классе, будет вызван во время инициализации этого класса — до вызова всякого из других его способов. Тут мы меняем местами реализацию базового способа addObject: и нашего способа logAddObject: . Обратите внимание на «рекурсивный» вызов в logAddObject: — это и есть обращение к перегруженной реализации основного способа.
Пример 3. Ассоциативные ссылки
Еще одним вестимым лимитацией категорий является неосуществимость создания в них новых переменных экземпляра. Пускай, скажем, вам требуется добавить новое качество к библиотечному классу UITableView — ссылку на «заглушку», которая будет показываться, когда таблица пуста:
«Из коробки» данный код трудиться не будет, вы получите исключение во время выполнения программы. Эту загвоздку дозволено обойти, применяя функционал ассоциативных ссылок:
Всякий объект вы можете применять как ассоциативный массив, объединяя с ним другие объекты с поддержкой функции objc_setAssociatedObject . Для ее работы требуется ключ, по которому вы потом сумеете извлечь необходимый вам объект назад, применяя вызов objc_getAssociatedObject . При этом вы не можете применять скопированное значение ключа — это должен быть именно тот объект (в примере — указатель), тот, что был передан в вызове objc_setAssociatedObject .
Завершение
Сейчас вы располагаете базовым представлением о том, что такое Objective-C Runtime и чем он может быть пригоден разработчику на практике. Для желающих узнать вероятности библиотеки глубже, могу порекомендовать следующие добавочные источники:
В данном посте я хочу обратиться к теме, о которой многие начинающие iPhone-разработчики часто имеют смутное представление: Objective-C Runtime. Многие знают, что он существует, но каковы его возможности и как его использовать на практике?
Попробуем разобраться в базовых функциях этой библиотеки. Материал основан на лекциях, которые мы в Coalla используем для обучения сотрудников.
Что такое Runtime?
Objective-C задумывался как надстройка над языком C, добавляющая к нему поддержку объектно-ориентированной парадигмы. Фактически, с точки зрения синтаксиса, Objective-C — это достаточно небольшой набор ключевых слов и управляющих конструкций над обычным C. Именно Runtime, библиотека времени выполнения, предоставляет тот набор функций, которые вдыхают в язык жизнь, реализуя его динамические возможности и обеспечивая функционирование ООП.
Базовые структуры данных
Функции и структуры Runtime-библиотеки определены в нескольких заголовочных файлах: objc.h , runtime.h и message.h . Сначала обратимся к файлу objc.h и посмотрим, что представляет из себя объект с точки зрения Runtime:
Мы видим, что объект в процессе работы программы представлен обычной C-структурой. Каждый Objective-C объект имеет ссылку на свой класс — так называемый isa-указатель. Думаю, все видели его при просмотре структуры объектов во время отладки приложений. В свою очередь, класс также представляет из себя аналогичную структуру:
Класс в Objective-C — это полноценный объект и у него тоже присутствует isa-указатель на «класс класса», так называемый метакласс в терминах Objective-C. Аналогично, С-структуры определены и для других сущностей языка:
Функции Runtime-библиотеки
- Манипулирование классами: class_addMethod , class_addIvar , class_replaceMethod
- Создание новых классов: class_allocateClassPair , class_registerClassPair
- Интроспекция: class_getName , class_getSuperclass , class_getInstanceVariable , class_getProperty , class_copyMethodList , class_copyIvarList , class_copyPropertyList
- Манипулирование объектами: objc_msgSend , objc_getClass , object_copy
- Работа с ассоциативными ссылками
Пример 1. Интроспекция объекта
Рассмотрим пример использования Runtime библиотеки. В одном из наших проектов модель данных представляет собой plain old Objective-C объекты с некоторым набором свойств:
Для удобства отладки хотелось бы, чтобы при выводе в лог печаталась информация о состоянии свойств объекта, а не нечто вроде . Поскольку модель данных достаточно разветвленная, с большим количеством различных подклассов, нежелательно писать для каждого класса отдельный метод description , в котором вручную собирать значения его свойств. На помощь приходит Objective-C Runtime:
Метод, определенный в общем суперклассе объектов модели, получает список всех свойств объекта с помощью функции class_copyPropertyList . Затем значения свойств собираются в NSDictionary , который и используется при построении строкового представления объекта. Данный алгоритм раработает только со свойствами, которые являются Objective-C объектами. Проверка типа осуществляется с использованием функции property_getAttributes . Результат работы метода выглядит примерно так:
2013-05-04 15:54:01.992 Test[40675:11303] COConcreteObject: name = Foo;
quantity = 10;
title = bar;
>
Вызов objc_msgSent инициирует процесс поиска реализации метода, соответствующего селектору, переданному в функцию. Реализация метода ищется в так называемой таблице диспетчеризации класса. Поскольку этот процесс может быть достаточно продолжительным, с каждым классом ассоциирован кеш методов. После первого вызова любого метода, результат поиска его реализации будет закеширован в классе. Если реализация метода не найдена в самом классе, дальше поиск продолжается вверх по иерархии наследования — в суперклассах данного класса. Если же и при поиске по иерархии результат не достигнут, в дело вступает механизм динамического поиска — вызывается один из специальных методов: resolveInstanceMethod или resolveClassMethod . Переопределение этих методов — одна из последних возможностей повлиять на Runtime:
Пример 2. Method Swizzling
Одна из особенностей категорий в Objective-C — метод, определенный в категории, полностью перекрывает метод базового класса. Иногда нам требуется не переопределить, а расширить функционал имеющегося метода. Пусть, например, по каким-то причинам нам хочется залогировать все добавления элементов в массив NSMutableArray . Стандартными средствами языка этого сделать не получится. Но мы можем использовать прием под названием method swizzling:
Мы перегружаем метод load — это специальный callback, который, если он определен в классе, будет вызван во время инициализации этого класса — до вызова любого из других его методов. Здесь мы меняем местами реализацию базового метода addObject: и нашего метода logAddObject: . Обратите внимание на «рекурсивный» вызов в logAddObject: — это и есть обращение к перегруженной реализации основного метода.
Пример 3. Ассоциативные ссылки
Еще одним известным ограничением категорий является невозможность создания в них новых переменных экземпляра. Пусть, например, вам требуется добавить новое свойство к библиотечному классу UITableView — ссылку на «заглушку», которая будет показываться, когда таблица пуста:
«Из коробки» этот код работать не будет, вы получите исключение во время выполнения программы. Эту проблему можно обойти, используя функционал ассоциативных ссылок:
Любой объект вы можете использовать как ассоциативный массив, связывая с ним другие объекты с помощью функции objc_setAssociatedObject . Для ее работы требуется ключ, по которому вы потом сможете извлечь нужный вам объект назад, используя вызов objc_getAssociatedObject . При этом вы не можете использовать скопированное значение ключа — это должен быть именно тот объект (в примере — указатель), который был передан в вызове objc_setAssociatedObject .
В данном посте я хочу обратиться к теме, о которой многие начинающие iPhone-разработчики часто имеют смутное представление: Objective-C Runtime. Многие знают, что он существует, но каковы его возможности и как его использовать на практике?
Попробуем разобраться в базовых функциях этой библиотеки. Материал основан на лекциях, которые мы в Coalla используем для обучения сотрудников.
Что такое Runtime?
Objective-C задумывался как надстройка над языком C, добавляющая к нему поддержку объектно-ориентированной парадигмы. Фактически, с точки зрения синтаксиса, Objective-C — это достаточно небольшой набор ключевых слов и управляющих конструкций над обычным C. Именно Runtime, библиотека времени выполнения, предоставляет тот набор функций, которые вдыхают в язык жизнь, реализуя его динамические возможности и обеспечивая функционирование ООП.
Базовые структуры данных
Функции и структуры Runtime-библиотеки определены в нескольких заголовочных файлах: objc.h , runtime.h и message.h . Сначала обратимся к файлу objc.h и посмотрим, что представляет из себя объект с точки зрения Runtime:
Мы видим, что объект в процессе работы программы представлен обычной C-структурой. Каждый Objective-C объект имеет ссылку на свой класс — так называемый isa-указатель. Думаю, все видели его при просмотре структуры объектов во время отладки приложений. В свою очередь, класс также представляет из себя аналогичную структуру:
Класс в Objective-C — это полноценный объект и у него тоже присутствует isa-указатель на «класс класса», так называемый метакласс в терминах Objective-C. Аналогично, С-структуры определены и для других сущностей языка:
Функции Runtime-библиотеки
- Манипулирование классами: class_addMethod , class_addIvar , class_replaceMethod
- Создание новых классов: class_allocateClassPair , class_registerClassPair
- Интроспекция: class_getName , class_getSuperclass , class_getInstanceVariable , class_getProperty , class_copyMethodList , class_copyIvarList , class_copyPropertyList
- Манипулирование объектами: objc_msgSend , objc_getClass , object_copy
- Работа с ассоциативными ссылками
Пример 1. Интроспекция объекта
Рассмотрим пример использования Runtime библиотеки. В одном из наших проектов модель данных представляет собой plain old Objective-C объекты с некоторым набором свойств:
Для удобства отладки хотелось бы, чтобы при выводе в лог печаталась информация о состоянии свойств объекта, а не нечто вроде . Поскольку модель данных достаточно разветвленная, с большим количеством различных подклассов, нежелательно писать для каждого класса отдельный метод description , в котором вручную собирать значения его свойств. На помощь приходит Objective-C Runtime:
Метод, определенный в общем суперклассе объектов модели, получает список всех свойств объекта с помощью функции class_copyPropertyList . Затем значения свойств собираются в NSDictionary , который и используется при построении строкового представления объекта. Данный алгоритм раработает только со свойствами, которые являются Objective-C объектами. Проверка типа осуществляется с использованием функции property_getAttributes . Результат работы метода выглядит примерно так:
2013-05-04 15:54:01.992 Test[40675:11303] COConcreteObject: name = Foo;
quantity = 10;
title = bar;
>
Вызов objc_msgSent инициирует процесс поиска реализации метода, соответствующего селектору, переданному в функцию. Реализация метода ищется в так называемой таблице диспетчеризации класса. Поскольку этот процесс может быть достаточно продолжительным, с каждым классом ассоциирован кеш методов. После первого вызова любого метода, результат поиска его реализации будет закеширован в классе. Если реализация метода не найдена в самом классе, дальше поиск продолжается вверх по иерархии наследования — в суперклассах данного класса. Если же и при поиске по иерархии результат не достигнут, в дело вступает механизм динамического поиска — вызывается один из специальных методов: resolveInstanceMethod или resolveClassMethod . Переопределение этих методов — одна из последних возможностей повлиять на Runtime:
Пример 2. Method Swizzling
Одна из особенностей категорий в Objective-C — метод, определенный в категории, полностью перекрывает метод базового класса. Иногда нам требуется не переопределить, а расширить функционал имеющегося метода. Пусть, например, по каким-то причинам нам хочется залогировать все добавления элементов в массив NSMutableArray . Стандартными средствами языка этого сделать не получится. Но мы можем использовать прием под названием method swizzling:
Мы перегружаем метод load — это специальный callback, который, если он определен в классе, будет вызван во время инициализации этого класса — до вызова любого из других его методов. Здесь мы меняем местами реализацию базового метода addObject: и нашего метода logAddObject: . Обратите внимание на «рекурсивный» вызов в logAddObject: — это и есть обращение к перегруженной реализации основного метода.
Пример 3. Ассоциативные ссылки
Еще одним известным ограничением категорий является невозможность создания в них новых переменных экземпляра. Пусть, например, вам требуется добавить новое свойство к библиотечному классу UITableView — ссылку на «заглушку», которая будет показываться, когда таблица пуста:
«Из коробки» этот код работать не будет, вы получите исключение во время выполнения программы. Эту проблему можно обойти, используя функционал ассоциативных ссылок:
Любой объект вы можете использовать как ассоциативный массив, связывая с ним другие объекты с помощью функции objc_setAssociatedObject . Для ее работы требуется ключ, по которому вы потом сможете извлечь нужный вам объект назад, используя вызов objc_getAssociatedObject . При этом вы не можете использовать скопированное значение ключа — это должен быть именно тот объект (в примере — указатель), который был передан в вызове objc_setAssociatedObject .
Многие Cocoa разработчики имеют довольно смутное представление об Objective-C Runtime API. Они знают, что он существует где-то там (некоторые не знают даже этого!), что он важен, и Objective-C без него неработоспособен, но обычно этим все знания и ограничиваются.
Сегодня я расскажу о том, как устроен Objective-C на уровне Runtime и о том, как конекретно вы можете это использовать.
Объекты
В Objective-C мы постоянно имеем дело с объектами, но что же такое объект на самом деле? Давайте попробуем соорудить что-то, что поможет пролить нам свет на этот вопрос.
Во-первых, всем нам известно, что мы ссылаемся на объекты с помощью указателей, например, NSObject *. Также мы знаем, что создаём мы их с помощью +alloc. Всё, что мы може узнать об этом из документации, так это то, что это происходит путём вызова +allocWithZone:. Продолжая нашу цепочку исследований, мы обнаруживаем NSDefaultMallocZone, который создаётся с помощью обыкновенного malloc. И всё!
Но что из себя представляют созданные объекты? Что ж, посмотрим:
Мы соорудили иерархию классов, каждый из которых содержет в себе переменные, и заполнили их вполне очевидными значениями. Затем мы извлекли данные в удобоваримый вид, исползьуя malloc_size, дабы получить правильную длину и воспользовались NSData, чтобы распечатать всё в hex. Вот, что у нас получилось на выходе:
Мы видим, что класс последовательно заполнил ячейки памяти—сначала переменную A, потом его наследника B, а потом C. Всё просто!
Но что за 20300000 в самом начале? Они идут перед A, и потому, скорее всего, принадлежат NSObject. Посмотрим-ка на определение NSObject.
Как видим, вновь какая-то пременная. Но что это за Class такой? Переходим по определению, которое нам предлагает Xcode и попадаем в usr/include/objc/objc.h, в котором находим следущее:
Идём дальше в /usr/include/objc/runtime.h и видим:
Таким образом, Class это указатель на структуру, которая… Начинается с ещё одного Class
Посмотрим ещё один класс, NSProxy
И тут он есть. Ещё один, id, за которым может скрываться любой объект в Objective-C
И снова он. Очевидно, что каждый объект в Objective-C должен начинаться с Class isa, даже объекты классов. Так что же это такое?
Как следует из названия и типа, переменная isa указывает, какому классу принадлежит тот или иной объект. Каждый объект в Objective-C должен начинаться с isa, иначе runtime не будет знать, что же с ним делать. Вся информация о типе каждого конкретного объекта скрывается за этим крохотным указателем. Оставшийся кусок объекта, с точки зрения runtime, представляет из себя просто огромный BLOB, не дающий никакой информации. Только лишь классы могут придать этому куску какой-то смысл.
Классы
Исследуя runtime.h, вы можете обнаружить множество функций для доступа и изменению этих элементов. Каждая функция начинается с префикса, который показывает, с чем она имеет дело. Базовые начинаются на objc_, функции для работы с классами на class_, и так далее. Например, вы можете вызвать class_getInstanceMethod, чтобы узнать информацию о конкретном методе, такую как список аргументов/тип возвращаемого значения. Или же можете добавить новый метод с помощью class_addMethod. Вы даже можете создавать целые классы с помощью objc_allocateClassPair прямо во время исполнения!
Практическое применеие
Заключение
Objective-C — это мощный язык, ключевую роль в динамичности которого играет всеохватывающий Runtime API. Быть может, не так уж и приятно возиться со всем этим C кодом, но возможности, которые он открывает, поистине огромны.
(прим. переводчика — для тех, кому уже не терпится поиграться со всей этой бесконечной динамичностью Objective-C, но не хочется разбираться с runtime.h, Mike Ash выложил на GitHub проект — обертку над runtime.h, предоставляющую полный доступ ко всем вкусностям, описаным выше, но в привычном Objective-C синтаксисе.)
В этой статье основное внимание будет уделено описанию принципов работы Objective-C Runtime и деталям внутреннего устройства этого языка, что в будущем поможет проводить более глубокий и качественный анализ безопасности IOS-приложений.
Автор: Пратик Джианчандани (Prateek Gianchandani)
Почти все «родные» IOS-приложения написаны на Objective-C. Все эти приложения используются библиотеку Cocoa, содержащую набор высокоуровневых API-функций, которые заметно упрощают разработку приложений под Mac и IOS. Также в Cocoa есть среда выполнения (runtime environment) для приложений. В этой статье основное внимание будет уделено описанию принципов работы Objective-C Runtime и деталям внутреннего устройства этого языка, что в будущем поможет проводить более глубокий и качественный анализ безопасности IOS-приложений.
Objective-C Runtime
Objective-C представляет собой динамически ориентированный язык (runtime-oriented language). При этом возникает закономерный вопрос, что же такое динамический язык (runtime language)? Динамический язык – это такой язык, когда все решения (в том числе и при вызове функций) принимаются во время выполнения приложений. Является ли Objective-C динамическим языком? Ответ: нет. Objective-C – динамически ориентированный язык, а это означает, что принятие решения во время выполнения приложения происходит только там, где это возможно. Как говорилось ранее, библиотека Cocoa предоставляет среду выполнения, которая необходима IOS-приложениям. На рисунке ниже приводится параграф из документации Apple, проясняющий многие вещи.
Рисунок 1: Выдержка из документации Apple для языка Objective-C
Перевод текста с Рисунка 1: Приложения, написанные на языке Objective-C, принимают решения во время выполнения везде, где это возможно (то есть происходит динамическое исполнение кода). Это означает, что для работоспособности приложения требуется не только компилятор, но и среда выполнения, которая предназначена для запуска скомпилированного кода. Для языка Objective-C среда выполнения функционирует как операционная система, которая отвечает за работоспособность приложений, написанных на Objective-C.
Теперь проверим, импортируется ли динамическая библиотека (runtime library) внутри проектов или нет. В идеале импорт должен происходить в каждом IOS-приложении. Чтобы проверить это, подключитесь к устройству и зайдите в директорию с приложениями.
Рисунок 2: Содержимое директории /var/mobile/Applications
Теперь введите «ls *» для вывода списка всех директорий, включая поддиректории.
Рисунок 3: Содержимое директории /var/mobile/Applications вместе с поддиректориями каждой директории
Рассмотрим содержимое директории приложения BADLAND (весьма популярная игра для IOS). Заходим внутрь директории BADLAND.app и смотрим бинарный файл Badland при помощи утилиты otool.
Рисунок 4: Отображение содержимого бинарного файла при помощи утилиты otool
Из рисунка выше мы видим, что импортируется достаточно большое количество библиотек. Импорт библиотеки objc-runtime показано на рисунке ниже.
Рисунок 5: Импорт библиотеки objc-runtime
Библиотека objc-runtime делает возможным манипуляцию кодом во время выполнения программы, написанной на Objective-C. По умолчанию, эта библиотека используется во всех IOS-приложениях. К примеру, рассмотрим приложение Google Maps для платформы IOS (также при помощи утилиты otool).
Рисунок 6: Анализ бинарного файла приложения Google Maps при помощи otool
Как видно из Рисунка 6, в приложении Google Maps также происходит импорт библиотеки Objective-C Runtime.
Динамический анализ приложения при помощи GDB
В этом разделе мы рассмотрим техники анализа во время выполнения приложения при помощи GDB. Первым делом необходимо установить корректную версию этого отладчика. Та версия, которая доступна через Cydia, не работает, и вам необходимо загрузить бинарный файл из других источников. После этого при помощи sftp загрузите файл gdb на устройство, как показано на рисунке ниже.
Рисунок 7: Процедура загрузки бинарного файла на устройство при помощи sftp
Далее устанавливаем права, необходимые для запуска отладчика.
Рисунок 8: Установка прав, необходимых для запуска отладчика
Чтобы подцепиться к запущенному процессу, необходимо вначале убедиться, что процесс запущен. Мы будем проводить тестирование на приложении Google Maps. Вначале запустим это приложение на устройстве и узнаем идентификатор процесса. Кроме того, необходимо убедиться в том, что приложение работает на переднем плане (foreground). Как видно из рисунка ниже, идентификатор процесса приложения Google Maps – 661 (в вашем случае идентификатор может быть другим).
Рисунок 9: Выяснение идентификатора процесса приложения Google Maps
Теперь подцепимся к процессу при помощи GDB.
Рисунок 10: Подцепляемся к процессу с идентификатором 661 при помощи GDB
Рисунок 11: Устанавливаем точку останова на метод objc_msgSend (break objc_msgSend) и команды, который выполняются во время срабатывания точки останова (x/a $r0 – печать $r0; x/a $r1 – печать $r1, c – продолжить выполнение приложения)
Рисунок 12: Информация, выдаваемая отладчиком, во время выполнения приложения
Как видно из Рисунка 12, эта техника хорошо помогает при анализе логики работы приложения. Повторюсь еще раз, возможно, конкретно в данном случае столь огромный объем информации может быть бесполезен во время настоящего анализа. Все это продемонстрировано лишь с целью показать вам, как много информации мы можем получить относительно реализации приложения.
Method Swizzling
Мы уже знаем, что все IOS-приложения во время запуска используют среду выполнения. Это означает, что многие решения принимаются во время выполнения приложения. Method Swizzling – еще одно оружие, которое мы можем использовать для модификации поведения IOS-приложения. Эта техника позволяет нам переопределить логику работы метода. Мы рассмотрим более подробно Method Swizzling в следующей статье.
Один хакер может причинить столько же вреда, сколько 10 000 солдат! Подпишись на наш Телеграм канал, чтобы узнать первым, как выжить в цифровом кошмаре!
Читайте также: