0ctf2019 pwn babyheap writeup
TOC
相对简单的一题,可以看成高个子当中的矮子,对于初学者来说还是非常难的。
源程序、相关文件下载:babyheap.zip 。
安全防护
ex@Ex:~/test$ checksec babyheap |
溢出点
在Update
函数里面有明显off by one
漏洞。
void __fastcall read_n(char *str, unsigned __int64 length) |
思路
- 压缩top chunk
- 触发 malloc_consolidate
- chunk overlaping
- 泄露地址
- 劫持top chunk
- 劫持__realloc_hook and __malloc_hook
- onegadget拿shell
压缩top chunk
当top chunk不足以分配需要的size时,会触发malloc_consolidate,然后free掉fastbin
,就是把fastbin
放入small bin
中。
# run out of the top chunk |
触发 malloc_consolidate
# Trigger consolidate |
上面修改unsorted bin
的size主要是为了后面的chunk overlaping
。
chunk overlaping
# Trigger second consolidate |
原理就是在malloc_consolidate
函数中,会把相邻的fastbin
进行合并:
if (!prev_inuse(p)) { |
由于上面我们已经多次触发malloc_consolidate
,所以heap当中的数据都已经写好了,可以绕过所有unlink
检查。
泄露地址
调试可得index 5
的地址离unsorted bin
最近,所以把unsorted bin
压缩到index 5
可控的范围内即可泄露main_arena
的地址。
Allocate(0x28) # index 7 |
劫持top chunk
Allocate(0x48) # index 8 |
利用 overlaping
修改fastbin的fd为main_arena_addr + 45
:
pwndbg> bin |
利用拿出来的main_arena+45
来控制top chunk。
劫持__realloc_hook and __malloc_hook
将top chunk指向__malloc_hook
附近即可控制__malloc_hook
,也就是main_arena_addr - 0x33
。
Allocate(0x58) # index 10 |
这里我说明一下,只劫持一个 __malloc_hook 是没有办法符合 onegadget 的约束条件的,需要组合 __realloc_hook 对栈进行偏移,使得 [rsp+0x70] 的值恰好为 NULL 。
onegadget拿shell
sh.sendline('1') |
完整脚本
#!/usr/bin/python2 |
运行实例
ex@Ex:~/test$ ./exp.py |
受随机化影响,可能要多试几次才能成功。
总结
0ctf这种知名的国际赛,题目质量特别的好,每一道题目都能学到很多东西。