绕过PXN保护

7月1日 mosec2016移动安全技术峰会 360的一篇议题 Android Root利用技术漫谈:绕过PXN 介绍一种通用的绕过pxn的技术,有别于传统rop/jop技术,通过利用内核中现有的功能模块实现pxn的绕过,不再需要寻找构造rop了。

利用逻辑

整个ppt用了很大的篇幅介绍了android漏洞利用的过程,而介绍这个新技术的就一页:
set_fs

内核中一些函数调用了set_fs(KERNEL_DS)以后,由于代码逻辑问题导致在函数调用返回之前没有恢复原来的old_fs,看下set_fs(KERNEL_DS)汇编如下:

1
2
3
4
5
6
7
8
9
10
11
STP             X29, X30, [SP,#-0x20+var_s0]!
MOV X29, SP
MOV X3, SP
STP X19, X20, [SP,#var_s10]
AND X19, X3, #0xFFFFFFFFFFFFC000
MOV X3, #0xFFFFFFFFFFFFFFFF
LDR X20, [X19,#8]
STR X3, [X19,#8]
...
LDP X19, X20, [SP,#var_s10]
LDP X29, X30, [SP+var_s0],#0x20

该函数实现了patch addr_limit操作,将进程改为任意读写,所以控制eip后触发一下这个函数就具有了任意地址读写能力,从而不用再去寻找rop来实现该过程。

总结

1.存在这种错误逻辑的函数本身就是一种漏洞,如果用户态进程能调用到该逻辑,直接就可以任意读写,完全不需要使用一个漏洞来配合跳转。

2.如果是在本进程控制的eip可以跳过去触发任意读写,但是如果控制的eip是在其他内核进程的话,这种做法是没有任何意义的。

3.任意读写之后还需要泄漏sp才能完成提权过程,后续泄漏sp还是需要rop做配合,所以这种方法也只是节省了一条rop,不过泄漏sp的rop比较容易找。当然也可通过暴力搜索获取当前的线程栈。

4.关于rop,其实找到几条之后还是比较通用的,可以写脚本去自动适配,用这个方法绕过pxn最理想的环境应该是:
控制的eip为当前进程 && 无法控制其他寄存器构造rop

思考

存在pxn的情况下,漏洞利用一般都是需要控制eip加上一个寄存器,这样后续可以构造rop来实现相关的提权操作,但只能控制eip的漏洞是无法很好的利用的,曾经我也是这样认为的。
但是最近找到了一种更通用的方法,不需要rop,不需要额外的寄存器,只要控制eip就可以进行提权,所以啊,漏洞利用真是一个容易打脸的事情。