staticinlinestructthread_info*current_thread_info(void)
{
registerunsignedlongspasm("sp");
return(structthread_info*)(sp&~(THREAD_SIZE1));
}
图3thread_info位置
获取进程的thread_info。因为ShellCode运行在内核空间,所以此时获取到的栈指针寄存器sp
就是内核栈的栈指针,在32位的内核中,屏蔽掉sp的低13位就能获取到thread_info。内核也
是采用这种方法来获取进程thread_info信息的。找到thread_info后,就能进一步找creds,然
后直接对creds的内存做修改即可提权。
然而,目前大多数的Android设备都开启了PXN保护,这让ret2usr攻击不再有效……
0x03bypassPXN常规方法
PXN的设计初衷就是阻断ret2usr这类攻击手段,让内核只执行内核空间的代码。类似
于《Linux内核ROP姿势详解(一)》一文中采用ROPbypassSMEP的方法,ARM平台下
bypassPXN也可以采用ROP技术。《PXN防护技术的研究与绕过》一文已经详细讲解了构建
内核ROP来bypassPXN的步骤,这里不再重复原文内容,大概介绍原文中未涉及到的小细
节。通过该文可知,bypassPXN时内核ROP主要完成三部分工作:泄漏内核sp值,计算
addr_limit地址和patchaddr_limit。这个过程的最终目的是patchaddr_limit,让用户态可以自
由访问内核空间,然后修改内核creds结构来提权。
可以看出泄漏内核sp值不仅仅用于找到addr_limit地址,更是用于提权时定位creds结
构在内存中的位置。用户态虽然可以自由访问内核空间,但并不能以指针的方式直接访问内核
,要以内核可接受的通信方式来间接访问,比如使用管道pipe来通信。之后对creds的每一次