Ответ 1
Трюк включает в себя некоторые (очень простые) обратные разработки и состоит из нескольких этапов; Я попытаюсь объяснить их как можно более четко.
Шаг Zero:, если приложение загружено из AppStore, оно зашифровано. Вы должны расшифровать его, используя один из сценариев/приложений, обычно используемых для взлома приложений; одна из команд командной строки script - poedCrack.sh(Google, вы найдете ее быстро на одном из сайтов вставки), одно приложение GUI - Crakculous (доступно в Cydia). Обратите внимание, что один из них необходим для простого (автоматического) дешифрования - метод ручного дешифрования слишком вовлечен, чтобы вставить ответ StackOverflow, поэтому я предлагаю эти инструменты.) Однако я никоим образом не поощряю вы можете взломать приложения! (В основном я прошу вас не использовать эти инструменты для своей первоначальной цели:) Если вы хотите посмотреть на процесс ручного дешифрования, зайдите сюда.
Шаг первый: вам нужно выполнить те классы, которые использует/создает приложение. Для этого вам понадобится утилита class-dump или class-dump-z. Это приложение командной строки отменяет бинарный исполняемый файл приложения и генерирует объявления интерфейса для всех классов Objective-C, которые приложение использует и имеет внутри. Здесь вы можете найти class-dump-z, более продвинутый и предпочтительный вариант .
Шаг второй: после того, как у вас есть объявления классов, вам придется угадать, какой класс делает что и когда (да, немного запутанно). Например, в одном из файлов, созданных из вышеприведенного приложения Google Chrome, с помощью класса-dump-z вы можете найти что-то подобное:
@interface ChromeUrlToolbar: UIToolbar {
UISearchBar *urlBar;
}
- (id)initWithFrame:(CGRect)frame;
- (void)loadURL:(NSURL *)url;
@end
Хорошо, это звучит хорошо, не так ли? Вы можете видеть, что его реализация имеет метод initWithFrame: (как и все подклассы UIView) - почему бы не попробовать его изменить?
Шаг третий: для этой модификации вам понадобится MobileSubstrate. MobileSubstrate - это библиотека разработчиков, созданная Saurik, создателем Cydia, для упрощения внедрения кода в приложения. Вы можете найти действительно хорошие учебные пособия в Интернете, в том числе этот. Итак, у вас есть класс, и вы хотите "перехватить" его, поэтому вы пишете такой код:
static IMP __original_init; // A
id __modified_init(id __self, SEL __cmd, CGRect frame) // B
{
__self = __original_init(__self, __cmd, frame); // C
// D
UIButton *newButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[newButton setTitle:@"Chrome Pwned"];
newButton.frame = CGRectMake(0, 0, 100, 40);
[__self addSubview:newButton];
return __self;
}
// E
__attribute__((constructor))
void init()
{
Class clazz = objc_getClass("ChromeUrlToolbar"); // F
MSHookMessageEx(clazz, @selector(initWithFrame:), __modified_init, &__original_init); // G
}
Объяснение: начните с конца. Функция init
(E) объявлена __attribute__((constructor))
. Это означает, что он автоматически вызывается, когда библиотека, которую мы создадим из этого кода, будет загружена в Chrome. Это именно то, что мы хотим, потому что хотим изменить наше поведение приложения до его начала.
В строке, помеченной // F
, мы фиксируем объект класса, который мы хотим изменить. Objective-C - очень динамичный язык; это означает, что мы можем получать и изменять информацию о классах и объектах во время выполнения. В строке, помеченной // G
, мы используем самую важную функцию API MobileSubstrate: MSHookMessageEx. Чтобы понять, как это работает, вы должны знать следующее: Objective-C сам реализуется как простая библиотека C - сам язык под капюшонами просто прост C. Поэтому каждое сообщение отправляется в Obejctive -C - фактически вызов функции C. Эта функция C имеет два специальных аргумента: self
и cmd
- первый - это указатель на передаваемый объект, последний - селектор (специальный уникальный указатель на имя отправляемого сообщения). Таким образом, что делает MSHookMessageEx, требуется класс и селектор, находит реализацию соответствующей им функции и обменивается этой функцией с функцией, предоставленной в самом ее третьем аргументе (__modified_init
в этом случае). Чтобы не потерять данные, он также возвращает функцию в свой 4-й параметр (здесь он __original_init
).
Итак, теперь инициализация панели инструментов URL-адреса Chrome перенаправляется на нашу функцию, что делать дальше? Ну, ничего особенного: сначала мы просто вызываем исходную функцию инициализации (обратите внимание на первые два специальных аргумента: __self и __cmd!), Которая создает панель инструментов, как обычно (эта строка кода обозначается символом // C
). Затем мы делаем фактическое изменение: в разделе // D
мы создаем UIButton, устанавливаем его заголовок и место и добавляем в качестве подзаголовка к нашей только что созданной панели инструментов. Затем, зная, что это функция инициализации, мы возвращаем исходный экземпляр вместе с нашим кодом кнопки, введенным в него.
Хорошо, это в основном то, что вам нужно знать об этом; если вам интересны более подробные сведения о том, как работает Objective-C и как вы можете создавать классные настройки iOS, я предлагаю вам прочитать официальную документацию Apple по этой темеи вы можете просматривать некоторые из моих настроек Cydia с открытым исходным кодом..
Я надеюсь, что это поможет вам!