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这种知名的国际赛,题目质量特别的好,每一道题目都能学到很多东西。