我已经做了很多尝试,终于使它工作了,但仍然没有用。 我试图更改__TEXT节中的某些变量,该节默认情况下是只读的,例如更改cryptid(和其他内容)
前一阵子,它在32位设备上工作了。但是以某种方式,在我使用64位命令后,它总是会失败。
如果我打以下几行,它当前会崩溃:
tseg->maxprot = tseg->initprot = VM_PROT_READ | VM_PROT_EXECUTE
要么
crypt->cryptid = 1
。
struct mach_header_64* mach = (struct mach_header_64*) _dyld_get_image_header(0);
uint64_t header_size = 0;
struct encryption_info_command_64 *crypt;
struct segment_command_64 *tseg;
struct dylib_command *protector_cmd;
// clean up some commands
void *curloc = (void *)mach + sizeof(struct mach_header);
for (int i=0;i<mach->ncmds;i++) {
struct load_command *lcmd = curloc;
if (lcmd->cmd == LC_ENCRYPTION_INFO_64) {
// save crypt cmd
crypt = curloc;
} else if (lcmd->cmd == LC_SEGMENT_64) {
struct segment_command_64 *seg = curloc;
if (seg->fileoff == 0 && seg->filesize != 0) {
header_size = seg->vmsize;
tseg = curloc;
}
}
if(i == mach->ncmds-1){
protector_cmd = curloc;
}
curloc += lcmd->cmdsize;
}
kern_return_t err;
// make __TEXT temporarily writable
err = vm_protect(mach_task_self(), (vm_address_t)mach, (vm_size_t)header_size, false, VM_PROT_ALL);
if (err != KERN_SUCCESS) exit(1);
// modify the load commands
// change protection of __TEXT segment
tseg->maxprot = tseg->initprot = VM_PROT_READ | VM_PROT_EXECUTE;
// change cryptid
crypt->cryptid = 1;
答案 0 :(得分:3)
更改加载命令毫无意义。加载程序时,加载命令已被处理(必须在您的代码可以运行之前)。它们对页面的保护没有进一步的影响。
您显然已经知道vm_protect()
函数。那么为什么不使用它使文本段本身可写而不是尝试使加载命令可写呢?
使用getsegmentdata()
在内存中定位该段肯定比查看加载命令(必须向其中添加幻灯片)简单得多。
除此之外,如果iOS允许您这样做,我会感到惊讶。普遍禁止运行时可修改的代码(非常狭窄的例外)。