在应用程序运行时如何修改应用程序中的各个汇编指令?
我正在为现有应用程序编写移动基板调整。在tweak的构造函数(MSInitialize
)中,我需要能够在应用程序的代码中重写单个指令。我的意思是,我希望修改应用程序的地址空间中的多个位置,但在每个实例中,只需要修改一条指令。我已经为应用程序禁用了ASLR,并且知道要修补的指令的确切内存地址,并且我有新指令的十六进制字节(作为char [],但这是不重要的,并且必要时可以更改)。我只需要弄清楚如何进行更改。
我知道iOS使用数据执行保护(DEP)来指定可执行内存页面也不可写,反之亦然,但我知道可以在越狱设备上绕过它。我也知道iDevices使用的ARM处理器有一个指令缓存,需要更新以反映更改。但是,我甚至不知道从哪里开始这样做。
所以,为了回答肯定会被问到的问题,我没有尝试过任何事情。这不是因为我很懒;相反,这是因为我完全不知道如何实现这一目标。任何帮助都将非常感激。
如果它有帮助,我的最终目标是在移动基板调整中使用它来挂钩App Store应用程序。以前,为了修改这个应用程序,必须先破解它来解密应用程序,以便修补二进制文件。我想做到这一点,所以人们不必破解应用程序,因为这可能导致盗版,我强烈反对。我不能正常使用Mobile Substrate,因为所有的工作都是用C ++完成的,而不是Objective-C,并且应用程序被剥离,没有任何符号可以使用MSHookFunction
。
答案 0 :(得分:5)
完全忘了我问过这个问题,所以我会告诉我现在最终的结果。评论应解释其运作方式和原因。
#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;
}
答案 1 :(得分:4)
vm_protect to w ^ x,假设你越狱越好(例如,如果mobilesubstrate有效)
答案 2 :(得分:3)
如上所述,从处理器寄存器写入指令存储器有点棘手。尤其是iPhone,因为Apple试图将处理器细节保密。
内存访问权限是第一个问题。可执行内存通常不可写。但是,如果克服了这个问题,那么就需要通过一些方法将数据从处理器寄存器中移出并进入指令流水线。通常,存在同步指令,其强制对它们之前和之后的存储器访问的特定顺序,以及高速缓存命令,其强制脏写入数据到存储器并清除干净且可能过时的读取数据。这两者都高度依赖于处理器的详细实现。
Arm Web上有很好的手册,详细解释了特定处理器的这些内容。但是,iPhone中的处理器是否符合公共Arm手册所说的内容,我不知道。
这是一个开始了解一个处理器的Arm内存同步模型的地方: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0092b/ch04s03s04.html 然后继续讲述如何通过写入控制寄存器来刷新指令高速缓存。当然可以为Arm处理器编写自修改代码,因为在那本手册的某个地方,我发现了一个声明,说它有时是不可避免的,必须得到支持。
(我不是说这是一个答案。但它不符合评论。)