Пишем полноценный твик для iOS с помощью iOSOpenDev

в 11:22, , рубрики: iOS, jailbreak, разработка под iOS, метки:

Доброго времени суток!

Сегодня я хотел бы вновь затронуть тему разработки jailbreak-программ под iOS. В русскоязычном интернете довольно проблематично найти что-то понятное новичкам, поэтому я попытаюсь исправить это недоразумение и объяснить как решаются некоторые моменты.

Установка ПО, настройка среды и устройства, написание твика с нуля — именно это ждёт вас под катом. Если вам интересно, как поменять часть iOS под себя — добро пожаловать.

Начнём!

Что нам потребуется?

  • Компьютер под управлением Mac OS X с утилитами git, dpkg;
  • Xcode с установленными Command Line tools (я использую 5.1.1, однако, подходит 4.0+);
  • Theos;
  • Пакет iOSOpenDev;
  • iУстройство с jailbreak'ом и установленным OpenSSH.

Подготовка

Первым шагом будет установка Xcode. Его вы можете скачать с Mac AppStore, а так же с страницы загрузок на сайте Apple. Подробно на этом останавливаться не буду.

Следом нужно поставить theos. Нам говорят, что его можно запихать на любую платформу, и он будет работать, но сегодня мы не изобретаем велосипед делаем всё на родной для iOS SDK системе.

Скачиваем theos в папку /opt/theos. Можно ставить в любую папку, но на свой страх и риск:

export THEOS=/opt/theos
git clone git://github.com/DHowett/theos.git $THEOS

На этом настройка c theos можно закончить.

Скачиваем iOSOpenDev и запускаем инсталлер. Он сделает всё за вас.
В случае возникновения неизвестной ошибки скорее всего приложение называется не «Xcode.app» или вы его не запускали вовсе.

Халява закончилась. Время настройки переменных.
Открываем ~/.bash_profile и редактируем следующие строчки:

export iOSOpenDevDevice=айпи.адрес.вашего.устройства

Теперь iOSOpenDev будет знать IP вашего устройства, осталось только разрешить подключаться по SSH без запроса пароля и скачать всю необходимую базу библиотек:

iod-setup base
iosod sshkey -h <IP устройства>

Дважды вводим пароль устройства, и, если запросит — придумываем пароль для кейчейна.
Более того, нужно скачать пачку хеадеров и положить в /opt/iOSOpenDev/include.

Тут сложнее всего с IOSurfaceAPI.h, так как он не является свободно распространяемым кодом. Но если вы не сможете его добыть из системы (на Mac OS X 10.10 я его не нашел), то заберите «заглушку» из папки _fallback, для нашего разбора будет достаточно и её.

На этом установку можно считать завершенной.

Пишем основу

Вся разработка будет проходить в Xcodе, хотя с некоторыми ограничениями.

Создаём новый проект и встречаем новый пункт «iOSOpenDev».

Пишем полноценный твик для iOS с помощью iOSOpenDev - 1

Нам требуется Logos Tweak:

Пишем полноценный твик для iOS с помощью iOSOpenDev - 2

Заполняем информацию о проекте. Include Simple PreferenceLoader добавит в проект простой блок настроек в Settings.app. Но о нём позже.

Теперь мы должны сделать то, что Xcode сам не делает — добавить в список для линковшика UIKit.framework и libsubstrate.dylib (последняя лежит в /opt/iOSOpenDev/lib/).

Пишем полноценный твик для iOS с помощью iOSOpenDev - 3

После этого заходим в наш .xm файл, сносим директиву #error и нажимаем на сборку. Первая сборка будет неудачной, а вторая должна быть успешной, это нормально. Еще в xm файле нет подсветки синтаксиса, но это решается закрытием и открытием Xcode после первой сборки.

Расставим все точки над «i»: .xm файл отвечает за код твика, а .mm файл является «промежуточным», он автоматически генерируется logos-препроцессором и потом компилируется.

Первые шаги

Сегодня мы будем менять унылую надпись «Разблокируйте» экрана блокировки на свой текст.

Во-первых, было бы хорошо раздобыть хеадеры бинарника «подопытного». Со SpringBoard все гораздо проще — народ готов выкладывать хеадеры спрингбоарда для каждой версии iOS. Но если вы хотите сделать их сами, то утилита class-dump-z вам в этом поможет.

Я пишу для iPad 4 на iOS 8.1, поэтому и хеадеры смотрим соответсвующие.

Есть два способа быстро найти то, что нам требуется. Первый — использовать cycript и посмотрев на иерархию объектов найти то, что нужно. Второй — искать поиском по содержимому хеадеров. В данном случае я решил поискать по запросу «unlockText» и нашел в классе SBLockScreenView такой вот метод:

- (id)_defaultSlideToUnlockText;

Предположим, что это то, что нам надо. Напишем первый набросок:

#import <UIKit/UIKit.h>

%hook SBLockScreenView

- (id)_defaultSlideToUnlockText
{
    return @"Привет!";
}

%end

Для компиляции с установкой на девайс выберите Build for profiling:

Пишем полноценный твик для iOS с помощью iOSOpenDev - 4

И, о, чудо! На удивление всё заработало с первого раза:

Пишем полноценный твик для iOS с помощью iOSOpenDev - 5

Наша основная цель — заставить меняться текст, поэтому создадим конструктор (%ctor) и будем подгружать настройки.

#import <UIKit/UIKit.h>

#define SETTINGS_FILE @"/var/mobile/Library/Preferences/ru.firemoon777.LockLabel8Bundle.plist"

NSDictionary *settings;

%hook SBLockScreenView

- (id)_defaultSlideToUnlockText
{
    return [settings objectForKey:@"Text"];
}

%end

static void loadSettings()
{
    settings = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE];
}

%ctor
{
    loadSettings();
}

Создаём панель настроек

Создадим новую цель: File — New — Target — iOS Open Dev — PreferenceBundle; Назовём её LockLabel8Bundle.
Есть большой плюс проекта с «сложными» PreferenceBundle'ом — в настройках можно сделать весь графический интерфейс для приложения и не заморачиваться с запуском от рута и подписями. Но есть и минус — панель в настройках и сам твик собираются в отдельных пакетах, поэтому для релиза придётся их ещё и объединить.

Можете попробовать собрать шаблон и полюбоваться на множество возможных встроенных PSSpecifier'ов.

Возможно, оно не скопилится сразу как надо. Значит, вы пропустили скачивание хеадров, про которые я говорил в начале статьи.

Из всех я оставлю только первую и последнюю группу, TextView и одну кнопку.

Пишем полноценный твик для iOS с помощью iOSOpenDev - 6

Еще можно подредактировать поле «label», чтобы не светить этим «Bundle».

У кнопки есть Action «respring:», поэтому опишем метод респрингa в LockLabel8BundleController:

- (void)respring:(PSSpecifier*)specifier
{
    system("killall SpringBoard");
}

С разработкой внутри настроек всё гораздо проще: здесь действуют те же законы, что и в обычных приложениях.

Исходный код доступен на гитхабе.

Поддержка нескольких версий iOS?

Когда твик становится из простого наброска масштабным проектом, возникает вопрос, а как организовать поддержку нескольких версий iOS так, чтобы не загружалось ничего лишнего? Тут на помощь приходят группы.

%group iOS6
// Методы для iOS6
%end

%group iOS78
// Методы для iOS7+
%end

%ctor
{
    if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) {
    	init(iOS78);
    } else {
    	init(iOS6);
    }
}

Подведём итог

iOSOpenDev всего лишь плагин для Xcode, но, на мой взгляд, он гораздо проще и удобнее, чем «голый» theos. На Mac OS X он заметно облегчает разработку iOS-твиков для новичков.

Автор: Firemoon

Источник

Поделиться

* - обязательные к заполнению поля