Инструкция программы патча iOS во время выполнения
Как можно изменить индивидуальные инструкции по сборке в приложении во время его запуска?
У меня есть настройка Mobile Substrate, которую я пишу для существующего приложения. В конструкторе tweak (MSInitialize
) мне нужно переписать отдельные инструкции в коде приложения. Я имею в виду, что в адресном пространстве приложения может быть несколько мест, которые я хочу изменить, но в каждом случае необходимо изменить только одну команду. Я уже отключил ASLR для приложения и знаю точный адрес памяти инструкции для исправления, и у меня есть шестнадцатеричные байты (как char [], но это не имеет значения и может быть изменено в случае необходимости) нового инструкция. Мне просто нужно выяснить, как выполнить изменения.
Я знаю, что iOS использует Data Execution Prevention (DEP), чтобы указать, что страницы исполняемой памяти не могут быть записаны и наоборот, но я знаю, что это возможно обойти это на взломанном устройстве. Я также знаю, что процессор ARM, используемый iDevices, имеет кеш команд, который необходимо обновить, чтобы отразить изменение. Однако я даже не знаю, с чего начать это делать.
Итак, чтобы ответить на вопрос, который в противном случае был бы задан, я ничего не пробовал. Это не потому, что я ленив; Скорее, это потому, что я совершенно не понимаю, как это можно сделать. Любая помощь вообще была бы оценена.
Изменить:
Если это вообще помогает, моя конечная цель - использовать это в настройке Mobile Substrate, которая перехватывает приложение App Store. Раньше, чтобы модифицировать это приложение, нужно было сначала взломать его, чтобы расшифровать приложение, чтобы двоичный файл мог быть исправлен. Я хочу сделать так, чтобы людям не пришлось взломать приложение, поскольку это может привести к пиратству, против которого я категорически против. Я не могу использовать Mobile Substrate обычно, потому что вся работа выполняется на С++, а не Objective-C, и приложение удаляется, не оставляя никаких символов для использования MSHookFunction
on.
Ответы
Ответ 1
Полностью забыл, что задал этот вопрос, поэтому покажу, с чем я закончил. Комментарии должны объяснить, как и почему это работает.
#include <stdio.h>
#include <stdbool.h>
#include <mach/mach.h>
#include <libkern/OSCacheControl.h>
#define kerncall(x) ({ \
kern_return_t _kr = (x); \
if(_kr != KERN_SUCCESS) \
fprintf(stderr, "%s failed with error code: 0x%x\n", #x, _kr); \
_kr; \
})
bool patch32(void* dst, uint32_t data) {
mach_port_t task;
vm_region_basic_info_data_t info;
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
vm_address_t region = (vm_address_t)dst;
vm_size_t region_size = 0;
/* Get region boundaries */
if(kerncall(vm_region(mach_task_self(), ®ion, ®ion_size, flavor, (vm_region_info_t)&info, (mach_msg_type_number_t*)&info_count, (mach_port_t*)&task))) return false;
/* Change memory protections to rw- */
if(kerncall(vm_protect(mach_task_self(), region, region_size, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY))) return false;
/* Actually perform the write */
*(uint32_t*)dst = data;
/* Flush CPU data cache to save write to RAM */
sys_dcache_flush(dst, sizeof(data));
/* Invalidate instruction cache to make the CPU read patched instructions from RAM */
sys_icache_invalidate(dst, sizeof(data));
/* Change memory protections back to r-x */
kerncall(vm_protect(mach_task_self(), region, region_size, false, VM_PROT_EXECUTE | VM_PROT_READ));
return true;
}
Ответ 2
vm_protect to w ^ x, предполагая, что вы джейлбрейк с приличным джейлбрейком (например, если mobilesubstrate работает)
Ответ 3
Запись в память команд из регистров процессора, как говорят другие выше, немного сложна. Особенно с iPhone, поскольку Apple пытается сохранить детали процессора в секрете.
Разрешения на доступ к памяти - первая проблема. Исполняемая память обычно не доступна для записи. Однако, если это будет преодолено, то есть немного танца, чтобы пройти, чтобы получить данные из регистров процессора и в конвейер команд. В общем, есть инструкции синхронизации, которые вынуждают определенный порядок доступа к памяти до и после них и команды кэша, которые заставляют грязные записи записывать данные в память и вымывают чистые и, возможно, устаревшие данные чтения. Оба они сильно зависят от детальной реализации процессора.
Рука В Интернете есть приятные руководства, которые подробно объясняют их для конкретных процессоров. Однако, говорят ли процессоры внутри iPhone о том, что говорят публичные ручные руководства, я понятия не имею.
Здесь место для начала понимания модели синхронизации памяти руки для одного процессора:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0092b/ch04s03s04.html
и далее идет о том, как очистить кеш команд путем записи в регистр управления. Конечно, можно написать самомодифицирующийся код для процессоров Arm, потому что где-то в этом руководстве я нашел выражение, в котором говорилось, что это иногда неизбежно, и его необходимо поддерживать.
(Я не утверждаю, что это ответ, но он не вписывается в комментарий.)