[原创]iOS inlinehook绕过反调试
开始
之前写过一篇iOS LLDB中基于内存单指令patch实现反反调试介绍了在LLDB中如何通过单指令patch的方式去绕过ptrace来反调试。但后面还有一些情况没有解决:如果不是调用ptrace函数,而是直接编写内联汇编的方式,调用对应的系统调用来间接实现反调试,那么这种方式之前的那种办法就不再可行。本文就准备解决那种用内联汇编的反调试方式。
两种绕过方案
这里有两种方案去绕过这种反调试:
- 静态内存匹配特征patch
- 实现一个简单的inlinehook动态hook绕过
静态内存匹配特征patch
在介绍思路之前,先看下一遍内联汇编去实现反调试的代码
asm volatile(
"mov x0,#31\n"
"mov x1,#0\n"
"mov x2,#0\n"
"mov x3,#0\n"
"mov x16,#26\n"
"svc #128\n"
);
这里可以看出原理就是调用了26号系统调用,那么我们是不是可以去代码段里面去搜索,找到满足该特征的代码位置,然后直接将svc置为 nop不就可以了?下面引出两个问题,如何去遍历代码段以及如何去修改?
获取代码段位置以及大小
void getTextSegmentAddr(struct segmentRange *textSegRange){
int offset = 0;
struct mach_header_64* header = (struct mach_header_64*)_dyld_get_image_header(0);
if(header->magic != MH_MAGIC_64) {
return ;
}
offset = sizeof(struct mach_header_64);
int ncmds = header->ncmds;
while(ncmds--) {
/* go through all load command to find __TEXT segment*/
struct load_command * lcp = (struct load_command *)((uint8_t*)header + offset);
offset += lcp->cmdsize;
if(lcp->cmd == LC_SEGMENT_64) {
struct segment_command_64 * curSegment = (struct segment_command_64 *)lcp;
struct section_64* curSection = (struct section_64*)((uint8_t*)curSegment + sizeof(struct segment_command_64));
// check current section of segment is __TEXT?
if(!strcmp(curSection->segname, "__TEXT") && !strcmp(curSection->sectname, "__text")){
uint64_t memAddr = curSection->addr;
textSegRange->start = memAddr + _dyld_get_image_vmaddr_slide(0);
textSegRange->end = textSegRange->start + curSection->size;
break;
}
}
}
return ;
}
代码不复杂,就是动态解析了自身内存里面的macho文件,根据macho文件格式找到代码段LC_SEGMENT_64(_TEXT)然后就能得到__text的开始位置以及大小。
内存搜索匹配ptrace内联汇编代码
void* lookup_ptrace_svc(void* target_addr, uint64_t size){
uint8_t * p = (uint8_t*)target_addr;
for(int i = 0; i < size ;i++ ){
/*
mov x16, #0x1a -> 0xd2800350
svc #0x80 -> 0xd4001001
*/
if (*((uint32_t*)p) == 0xd2800350 && *((uint32_t*)p+1) == 0xd4001001) {
return p;
}
p++;
}
return NULL;
}
传入的就是代码段的地址以及大小,然后遍历整个代码段,找到满足以下ptrace特征汇编代码
mov x16, #0x1a -> 0xd2800350 svc #0x80 -> 0xd4001001
然后就返回该地址。
patch代码(将svc改为nop)
iOS LLDB中基于内存单指令patch实现反反调试这篇文章介绍了如何去patch代码的原理,但当时遇到一个bug:在iOS11/12上面patch会失败,后面我花了一段时间去分析了失败的原因,后来也写了一篇文章去记录了分析的过程,感兴趣的可以访问iOS12内存patch remap bug分析
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
