出于应用安全防护的目的,安全开发人员为防止函数被HOOK(inlinehook/fishhook),一般会对敏感函数做SVC调用,如access/stat/open等函数。做SVC调用的方式明显由于直接调用和动态dlsym调用,隐蔽性得到增强,且Hook难度增加。具体实施形式可分为为裸函数或内联汇编。裸函数方式,即为一个独立函数,其他函数通过传递系统调用号和参数调用该函数内联汇编方式,会将SVC内联到每个调用函数中。这两者相比较,各有优势。裸函数方式,如果攻击者对此函数进行hook,可以很方便的通过内存校验检测出问题(如果直接用变量访问这段内存,也是很容易逆向分析,因此实际操作时可以使用一些间接引用技巧)。但无论如何,因为iOS上非越狱环境无法动态创建并执行代码,因此SVC这条汇编指令一定是存在于内存中,最常见的就是svc 0x80和svc 0x50(注意这个指令的立即数是默认忽略的,因此svc 0或者svc 0xffff效果都是一样的),对应机器码为01 10 00 D4,通常在逆向分析时,直接搜此二进制即可直达检测的关键处。为了对抗svc指令的检测和修改,缓解的方式也很多,比如:

将svc藏在特殊segment中 构造出包含01 10 00 D4的无效指令机器码来进行混淆。 将函数拆分成多个8字节函数,也就是2条指令,从而避免被inlinehook,因为inlinehook至少需要3条(Substitute)或4条(Substrate)指令才能成功 本文提出一种方式,可以更好的隐藏svc调用。libsystem_kernel.dylib是具体实现系统调用的动态库,通过逆向可以发现其包含大量的svc指令,那取巧的办法就是获取到这里svc的地址,并包装成函数进行调用,即可神不知鬼不觉达到隐藏svc并进行系统调用的目的。

arm64上具体实现代码如下,此代码通过获取libsystem_kernel模块地址,并爆搜指令的方式获取svc,并实现裸函数和内联函数两种调用方式,通过逆向可以发现,程序中并没有svc指令,完美达到目的!: 需要注意的是上述代码没有进行错误处理,这个实现是通过BCC指令,具体可以参照libsystem_kernel的反汇编。

好文推荐

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: