首页
社区
课程
招聘
[原创][原创]阿里聚安全iOS Anti-Debug分享
发表于: 2014-12-12 15:18 13703

[原创][原创]阿里聚安全iOS Anti-Debug分享

2014-12-12 15:18
13703

前言
移动平台攻防对抗技术的发展基本是沿着PC端发展轨迹在前进,从windows平台上的加壳到Android平台的APK加固,相信ipa的加固也已经不远了;windows平台下从ring3层到ring0层的反调试技术已经非常成熟,Android平台下的反调试技术已经出现了好几套不错的方案,今天由阿里聚安全专家与诸位来简单分享下iOS下的反调试技术。
PT_DENY_ATTACH
谈到debug,首先会想到的一个系统调用是ptrace,它主要用于实现断点调试和系统调用跟踪。从man ptrace的结果发现一个有趣的参数——PT_DENY_ATTACH:

图 1 man ptrace
PT_DENY_ATTACH是苹果增加的一个ptrace选项,用以防止gdb等调试器依附到某进程。用法如下:
ptrace(PT_DENY_ATTACH, 0, 0, 0);
直接上demo:

图 2 ptrace not found
那么问题就来了,编译报错:'sys/ptrace.h' file not found。iPhone真实环境下,根本就没有抛出sys/ptrace.h。但是幸运的是,我们依然可以使用dlopen和dlsym拿到ptrace。从man dlopen和man dlsym可以发现,当dlopen的path参数传入NULL时,dlopen将返回一个相当于RTLD_DEFAULT的handle;当dlsym接收到一个RTLD_DEFAULT的handle参数时,dlsym将根据载入的顺序搜索除以dlopen(xxx, RTLD_LOCAL)方式载入的所有mach-o文件。

图 3 man dlopen

图 4 man dlsym
根据以上的信息,反调试方法基本可以完成了,demo主要代码如下:

图 5 Anti debug Demo
尝试gdb依附会得到一个Segmentation fault错误:

图 6 运行demo

图 7 gdb依附
针对这种ptrace的反反调试方法其实很简单,通过修改ptrace的参数或者内存补丁就可以搞定,具体不在此详述。
另外,在某亿级用户的APP里面发现了相同的反调试方法,伪代码如下:

图 8 某APP反调试伪代码
注意,在dlfcn.h中有如下定义:
#define RTLD_GLOBAL        0x8
#define RTLD_NOW        0x2
sysctl
思路是通过sysctl查看信息进程里的标记,判断自己是否正在被调试。sysctl是用以查询内核状态的接口,并允许具备相应权限的进程设置内核状态。其定义如下:
int sysctl(int *name, u_int namelen, void *old, size_t *oldlen, void *newp, size_t newlen);
        name参数是一个用以指定查询的信息数组;
        namelen用以指定name数组的元素个数;
        old是用以函数返回的缓冲区;
        oldlen用以指定oldp缓冲区长度;
        newp和newlen在设置时使用;
当进程被调试器依附时,kinfo_proc结构下有一个kp_proc结构域,kp_proc的p_flag的被调试标识将被设置,即会进行类似如下的设置:
kinfo_proc. kp_proc. p_flag & P_TRACED
其中P_TRACED的定义如下:
#define P_TRACED        0x00000800  /* Debugged process being traced */
我们可以通过sysctl查询进程相应的kinfo_proc信息,查询函数的实现可以这样:

图 9 found debugger
name参数的4个元素表示通过本进程pid查询本进程信息。在主函数中检索is_debugged的返回值,返回为真时,即进程正在被调试,退出进程。测试结果如下:

图 10 gdb依附demo

图 11 demo发现debugger并退出
针对sysctl的反反调试的思路其实很简单,只需要在函数返回时清除p_flag标识位即可,根据sysctl.h文件中的定义:
#define        CTL_KERN        1
#define        KERN_PROC 14
#define        KERN_PROC_PID 1
以及sysctl的第二个参数为4,对sysctl下条件断点,在sysctl返回后,根据反编译二进制文件找到kproc的首地址,接下来找到p_flag相对kproc首地址的偏移,最后修改对应内存地址的值就OK了。
结语
iOS平台下的Anti-Debug方法相对于Linux下的要少很多,例如fork一个子进程,ptrace父进程进行检测方式不再奏效。而且,要完全防止程序被调试或者被逆向,理论上来说是不可能的。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 159
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
iOS下能做的比android确实要少很多
2014-12-12 15:21
0
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
前排留名
2014-12-12 15:21
0
雪    币: 61
活跃值: (97)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
发错板块了,请版主帮忙迁移至ios安全版,感谢!
2014-12-12 15:30
0
雪    币: 69
活跃值: (41)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
因为ios调试器特别难用,所以ios基本不调试.
1. clutch解密
2. ida逆向.
3. class-dump 头文件
4. cycript 动态分析.
5. 写Tweak,打log验证思路即可.

而且ios上的ptrace基本被阉割. lldb里面调试器的实现也不是通过ptrace来做的.
另外在正规的app里面,调用私有函数,小心过不了苹果的审核~ :).
android上,用fork()然后再ptrace做双进程保护,勉强够用,不过这一切都是纸老虎,安全防护,只有两个字:呵呵~~

ios和android上对抗,基本不对等. app没有root权限,恶意app可以有root.
哪怕安全防护可以有root了,恶意app一样有root,同等权限,没有安全可言.

还是大Windows好,自从加载驱动需要签名证书,敢玩这种内核对抗的,基本被吊销证书.
尤其是数字软件占领了驱动加载的坑,现在基本看不到这种同样具有内核权限的恶意程序了.
大Windows上,玩恶意的,基本也就是绕过下查杀,弹点小广告,赚点流量钱了~~

像这种检测isdebugged标志位,早几百年前就被在Windows的各位同学玩坏了~
现在Windows都玩到VT调试器了~~ 从早期用TRW2000,到OllyDbg,到SoftICE/syser/windbg内核调试再到VT调试,基本玩的都是权限~

权限不对等,基本都是扯淡~~ 一捅就破

另外吐槽下,fork这种蛋疼的机制. *nix 呢,从前是没有多线程这种概念的,所以fork()设计之初也是合理的. 后来参考了solaris/aix里面pthread的设计,*nix引入了多线程. 从此以后 多线程的进程,再来fork(),那就极其蛋疼了,一不小心就要出问题的(deadlock). 所以fork()后再ptrace(),做双进程保护? 再送两个字:呵呵~~
真心要学习大Windows的CreateProcess(),david cutler确实高瞻远瞩
设计fork()的那个年代,计算机还是奢侈品,内存啥的都不够用,copy-on-write也是对的.
估计Ken大爷也不会想到未来会发展成这样,竟然有人敢在多线程的进程中再fork()? 哈哈,ken大爷当年在贝尔实验室的时候,还没多线程呢~~

云风也有一篇专门吐槽fork()的帖子: 极不和谐的 fork 多线程程序
2014-12-13 01:06
0
雪    币: 1413
活跃值: (401)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
6
好文章不想移走啊,就留这儿吧
2014-12-13 01:47
0
雪    币: 188
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好文章,学习。
2014-12-19 18:26
0
游客
登录 | 注册 方可回帖
返回
//