64位栈溢出简单rop与简单例题的复现
首先还是找到关键函数
可以看到有read栈溢出漏洞,有system函数,查看字符串,还可以看到”/bin/sh”,既然这样,我们便可以一步到位直接通过rop将/bin/sh装入system函数中getshell。
如何通过rop实现传参呢?64位ELF是通过寄存器存放参数的,所以我们要想办法将/bin/sh放入rdi中并紧接着调用system函数。
那么该如何实现呢?我们假设一下,先通过pop edi将/bin/sh的地址压入edi中,然后再执行ret,并将此时的esp所指向栈空间的值改为system函数的值就可以实现getshell了。
也就是说,我们现在只需要考虑如何能执行pop edi,ret这样的指令了,这时候就需要ropgadget来实现了,通过rop搜索文件中pop edi ret指令的地址,获取这个地址以后,我们就可以通过栈溢出漏洞将返回地址修改为这段指令的地址。
也就是说,我们只需要将ret覆盖位pop edi ret代码的地址,接着覆盖/bin/sh的地址与system函数的地址就可以get shell 了!
开始复现一下例题
找到关键函数与关键的地址以后。尝试编写exp
from pwn import * |
运行一下试试
失败了,看了一下payload,好像并没有错啊,打开gdb调试。并没有什么异常。
那为什么会失败呢?这里就是一个坑了,大概就是类似于这样的指令
xmm0指令要求rsp+198h+var_158的值是对齐16byte(0x10),否则会直接触发中断从而crash。
具体可以看一下这个文章
所以想要解决这个坑,有三种方法,一是改变payload的长度,使用apyload对栈进行填充。
当然对于这道题来讲,增加payload进行填充也会遇到问题,是将填充栈用到的数据填充在payload最后面呢?这样的话并没有什么用,因为填充好了之前已经crash了,将其填充在中间?又会影响到ret指令对system函数的调用。所以我们可以换一个思路,改变一下填充数据,将填充数据修改为ret指令的地址,放在中间以后,可以使ret指令的返回地址仍指向ret,这样就仍然可以正常调用system函数了。
二是栈转移,这个不太懂,等学到了再说吧。