能力值:
(RANK:135 )
|
-
-
2 楼
mark!
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
谢谢楼主分享
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
楼主厉害,感谢分享
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
mark!
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
感谢分享
|
能力值:
( LV4,RANK:40 )
|
-
-
7 楼
thank you
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
代码段能直接修改吗 如果真是可以修改这个就厉害了 注入到进程想干嘛干嘛了。既然能改代码段了 顺便问问有没有实现PC上 写入INT3 接管异常来处理寄存器的技术
最后于 2019-9-25 15:38
被chaogelai编辑
,原因:
|
能力值:
( LV5,RANK:60 )
|
-
-
9 楼
chaogelai
代码段能直接修改吗 如果真是可以修改这个就厉害了 注入到进程想干嘛干嘛了。既然能改代码段了 顺便问问有没有实现PC上 写入INT ...
是的,就是改代码段。可以再调试器中做很多细腻的操作
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
xia0
是的,就是改代码段。可以再调试器中做很多细腻的操作
最后于 2019-9-26 13:08
被chaogelai编辑
,原因:
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
patchCode函数的代码怎么实现的?
|
能力值:
( LV3,RANK:30 )
|
-
-
12 楼
patchCode函数的代码怎么实现的?
|
能力值:
( LV5,RANK:60 )
|
-
-
13 楼
月光阴影
patchCode函数的代码怎么实现的?
https://github.com/4ch12dy/xia0LLDB/blob/master/debugme.py 这个文件里面有实现代码
|
能力值:
( LV5,RANK:60 )
|
-
-
14 楼
https://github.com/4ch12dy/xia0LLDB/blob/master/debugme.py 这个文件里面有实现代码
|
能力值:
( LV1,RANK:0 )
|
-
-
16 楼
感谢大佬分享,学到了
|
能力值:
( LV3,RANK:20 )
|
-
-
17 楼
之前改svc为nop都是用IDA,去patch的。楼主分享的很赞,去查找.text段,修改。学到了
|
能力值:
( LV1,RANK:0 )
|
-
-
18 楼
谢谢楼主分享
最后于 2020-10-23 16:51
被YunsChou编辑
,原因:
|
能力值:
( LV2,RANK:10 )
|
-
-
19 楼
饱学之士
|
能力值:
( LV8,RANK:120 )
|
-
-
20 楼
楼主的方案和frida、dobbyhook的hook很像 . 但是有一个祖传的bug一直没有解决,就是页边界问题.每个页0x4000 hook一次最少使用0x10 也就是4行代码. 如果hook的函数正好处于 0x3ffc 的时候就会崩溃.我的解决方案就是 ``` typedef struct _CopyMemoryInfo { void* hook_address; int copy_size; addr_t page_align_address; int offset; void* remap_page; }CopyMemoryInfo; // 检查是否可以hOOK if (!isHooking((size_t)function_address)) { return kCantHook; } // // 先创建一页内存, 将被hOOK的函数当前页整个拷贝进来 // 因为后面调用内核函数mach_vm_remap只能复制整页内存回去 int page_size = OSMemory::PageSize(); static mach_port_t self_port = mach_task_self(); addr_t page_align_address = ALIGN_FLOOR(function_address, page_size); int offset = static_cast<int>((addr_t)function_address - page_align_address); void* remap_page = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, VM_MAKE_TAG(255), 0); if(remap_page == NULL) { return kMemoryOperationError; } // 第一页从哪开始 - 拷贝几个字节 int curr_size = page_size - offset; if (curr_size >= 0x10) { curr_size = 0x10; } CopyMemoryInfo copy_list[2] = {{function_address, curr_size, page_align_address, offset, remap_page}, {0}}; // 这种情况下,HOOK会崩溃.因为已经在页的边界了,我们最低需求是0x10个字节. if(curr_size < 0x10) { // 下一页从哪开始 - 拷贝几个字节 void * next_address = (void*)((size_t)function_address + curr_size); copy_list[1].hook_address = next_address; copy_list[1].copy_size = 0x10 - curr_size; addr_t next_page_align_address = ALIGN_FLOOR(next_address, page_size); copy_list[1].page_align_address = next_page_align_address; copy_list[1].offset = static_cast<int>((addr_t)next_address - next_page_align_address); void* remap_page = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, VM_MAKE_TAG(255), 0); if(remap_page == NULL) { return kMemoryOperationError; } copy_list[1].remap_page = remap_page; } // new一块内存保存 old头部的0x10代码 void* oldCall = OSMemory::NewMemory(0x20); if(oldCall == NULL) { return kMemoryOperationError; } // 跳转代码长度 size_t size = (size_t)func_JumpCallEndin - (size_t)func_JumpCallBegin; // 将原始代码先保存起来 int cpyLength = 0; for(int i = 0; i < 2; i++) { if(copy_list[i].hook_address == 0) { break; } kern_return_t kr = vm_copy( self_port,(vm_address_t)copy_list[i].page_align_address, page_size, (vm_address_t)copy_list[i].remap_page); if (kr != KERN_SUCCESS) { munmap((void *)copy_list[i].remap_page, (mach_vm_address_t)page_size); return kMemoryOperationError; } // 将原始代码先保存起来 memcpy((void*)((size_t)oldCall + cpyLength), (void*)((size_t)copy_list[i].remap_page + copy_list[i].offset), copy_list[i].copy_size); cpyLength += copy_list[i].copy_size; } // // 检查前4条指令是否可以HOOK,如果可以HOOK // 从新计算被HOOK的4条指令中的相对地址,并且生成新的字节码 // 例如 // 10643ca70 : adrp x8, #0x10872a000 的字节码是 68 17 01 d0 // 如果我们原封不动的将上面的字节码拷贝出来在运行的时候 // 由于oldCall的地址并不是10643ca70取值的指针错误导致崩溃或者其他错误 // 所以要根据oldCall的地址从新计算 if(!makeOrigin(oldCall, 0x10, (size_t)function_address)) { for(int i = 0; i < 2; i++) { if(copy_list[i].remap_page != 0) { munmap((void *)copy_list[i].remap_page, (mach_vm_address_t)page_size);; } } OSMemory::SubOffset(0x20); return kCantHook; } // // 制作一个跳转回去被HOOK函数的中继函数 // 上面创建oldCall的时候是0x20字节 // 前0x10字节保存hOOK函数的头部的前0x10 // 后0x10字节保存我们跳到hook函数+0x10的地址 memcpy((void*)((size_t)oldCall + 0x10), (const void*)func_JumpCallBegin, size); *(size_t*)((size_t)oldCall + 0x10 + size) = (size_t)function_address + 0x10; *origin_call = oldCall; // 这里注意,将oldCall这一整页一定设置成 只读、执行. 否则崩溃,这个错误我排了4个小时血泪记录 mprotect(OSMemory::GetAddress(), page_size, PROT_READ | PROT_EXEC); // 设置跳转代码 char* buffer = new char[size + 8]; memset(buffer, 0, size + 8); memcpy(buffer, (void*)func_JumpCallBegin, size); *(size_t*)(buffer + 8) = (size_t)replace_call; cpyLength = 0; for(int i = 0; i < 2; i++) { if(copy_list[i].hook_address == 0) { break; } memcpy((void*)((size_t)copy_list[i].remap_page + copy_list[i].offset), (void*)((size_t)buffer + cpyLength), copy_list[i].copy_size); cpyLength += copy_list[i].copy_size; } delete [] buffer; for(int i = 0; i < 2; i++) { if(copy_list[i].hook_address == 0) { break; } mprotect((void *)copy_list[i].remap_page, page_size, PROT_READ | PROT_EXEC); mach_vm_address_t dest_page_address_ = (mach_vm_address_t)copy_list[i].page_align_address; vm_prot_t curr_protection, max_protection; kern_return_t kr = mach_vm_remap(self_port, &dest_page_address_, page_size, 0, VM_FLAGS_OVERWRITE | VM_FLAGS_FIXED, self_port, (mach_vm_address_t)copy_list[i].remap_page, TRUE, &curr_protection, &max_protection, VM_INHERIT_COPY); if (kr != KERN_SUCCESS) { return kMemoryOperationError; } // unmap the origin page int err = munmap((void *)copy_list[i].remap_page, (mach_vm_address_t)page_size); if (err == -1) { return kMemoryOperationError; } }
```
另外相对地址可以使用 Capstone + Keystone帮你完成
最后于 2021-1-16 16:07
被crazyearl编辑
,原因:
|