SROP攻击方式
SROP攻击方式
SROP,即 Sigreturn Oriented Programming,正是利用了Sigreturn机制的弱点来进行攻击的。
首先,系统在执行sigreturn系统调用的时候,不会对signa做检查,它不知道当前这个frame是不是之前保存的哪个frame。由于sigreturn会从用户栈上恢复所有寄存器的值,而用户栈是保存在用户进程的地址空间中的,是用户进程可读写的。如果攻击者可以控制栈,也就控制了所有寄存器的值,而这一切只需要一个gadget:“syscall;retn”,并且该gadget的地址在一些较老的系统上是没有随机化的,通常可以在vsyscall中找到,地址为0xffffffffff600000。如果是32位linux,则可以寻找int 80 指令,通常可以在vDSO中找到,但是这个地址可能是随机的。不同操作系统上的sigreturn如图所示。
攻击的具体流程:
1、首先利用一个栈溢出漏洞,将返回地址覆盖为一个指向sigreturn gadget 的指针。如果只有syscall,则将RAX设置为0xf,效果是一样的。在栈上覆盖上fake frame。
RSP:一个可写的内存地址
RIP: “syscall;retn” gadget的地址
RAX:read的系统调用号
RDI:文件描述符,即从哪儿读入
RSI:可写内存的地址,即写入到哪儿
RDX:读入的字节数,这里是306
2、sigreturn gadget 执行完之后,因为设置了RIP,会再次执行“syscall;retn” gadget。payload的第二部分就是通过这里读入文件描述符的。这一部分包含了3个“syscall;retn”、fake frame和其他的代码或数据。
3、接收完数据后,read函数返回,返回值即读入的字节数被放到RAX中,我们的可写内存被这些数据所覆盖,并且RSP指向了它的开头。然后“syscall;retn”被执行,由于RAX的值为306,即syncfs的系统调用号,该调用总是返回0,而0又是read的调用号。
4、再次执行“syscall;retn”,即read系统调用。这一次读入的内容不重要,重要的是数量,让它等于15,即sigreturn的调用号。
5、执行第三个“syscall;retn” ,即sigreturn系统调用。从第二个fake frame中恢复寄存器,这里是execve(“/bin/sh,...”).另外还可以调用mprotect将某段数据变为可执行的。
6、执行execve,拿到shell
PWNTOOLS srop模块
pwntools已经集成了srop的利用工具pwnlib.rop.srop,类SigreturnFrame的构造总共分为三种情况,结构和初始化的值会有所不同
(1)32位系统上运行32位程序。
(2)64位系统上运行32位程序。
(3)64位系统上运行64位程序。