概念
这里简单介绍下SROP的概念,主要是帮助读者理解和使用pwntools提供的SigreturnFrame工具实现漏洞利用。
我们都知道ROP吧,即利用.text段中的gadgets,这些gadgets都以ret指令作为结尾,以此串联起来实现我们想要的系统调用进而达到获取目标主机shell的目的。那么如何判断是哪种系统调用呢?这里是根据寄存器的值来进行判断的,只要将相应的寄存器值设置为对应参数,然后执行syscall或者int 80指令就可以实现相应的函数功能。这里推荐一个实现系统调用如何设置寄存器对应参数的网站和一个具体的例子:设置寄存器实现execve系统调用的博客。
好了,究其本质,ROP方法的思路都是通过gadgets设置寄存器的值来实现漏洞利用的,SROP也是从属于ROP方法中的一员。它利用了Linux系统信号处理过程中的漏洞,即在信号处理过程中会将用户态上下文环境及寄存器的值保存在用户态的栈中,处理完后再读取栈中的数据恢复寄存器的值。sigreturn系统调用就是处理完后那一阶段执行的系统调用,它会读取当前栈空间中的数据作为寄存器的值。因此这里我们利用栈溢出漏洞和sigreturn系统调用就可以实现SROP的攻击方法。首先利用栈溢出将返回地址设置为实现sigreturn系统调用的gadget,然后再将其后面的栈空间布置成我们想要设置的寄存器的值。待sigreturn系统调用执行完毕,此时的寄存器值,包括RSP/ESP和RIP/EIP都会被改变,所以SROP强大之处就是改变了所有的寄存器,这可以让我们实现任何想要的系统调用,但附带效果就是会改变栈顶指针RSP/ESP,有时候这并不是我们想要的。
SigreturnFrame的使用
使用SROP实现漏洞利用的思想也是比较简洁的,但是要在栈上构造所有寄存器的值,这个工程量比较大,好在可以使用pwntools中的SigreturnFrame类来简化我们的代码编写。具体操作如下面的代码所示:
from pwn import *
# 64位
# sigreturn 代表可以触发sigreturn调用的地址
# 其gadgets如下,只要使rax = 0xf,然后进行系统调用
"""
0x001 mov rax, 0Fh
0x002 syscall
0x003 ret
"""
sigreturn = 0x001
syscall = 0x002 # syscall gadget
context.arch = "amd64"
frame = SigreturnFrame(<