1.Fastbin Double Free
Double free及将一个堆块free两次,gdb中如下图所示

这样我们就可以将两个堆块申请在同一个位置,其中一个堆块是free状态,我们可以通过另一个堆块对fd指针进行修改
Fastbin Double Free能够成功利用的原因:
1.fastbin的堆块被释放后next_chunk的prev_inuse位不会被清空
2.fastbin在执行free的时候仅验证了main_arena直接指向的块,即链表指针头部的块。对于链表后面的块并没有进行验证
2.fastbin dump into stack
顾名思义,将堆块申请在栈上,控制栈上的数据,利用uaf漏洞,将fd指针改为要控制数据的地址-0x10(因为fd指针指的是堆块的头部,所以需要-0x10,才刚好使数据段落在要要控制数据的栈上),修改堆块的内容就可以控制栈上的数据
注:首先要伪造size位(0xn1)
ISMMAP位不能为1
inues位为0
size位为0x40
地址要64位:0/8
32位:0/4 对齐
在内存中构造了一个了一个堆块,还要怎么样才能让它 free
扩展用在fastbin attack打mallco使申请堆块大小受限制(<=0x60,也就是没发使堆块的size位为0x71)
在2.23和2.27的libc版本中,由于没有对top chunk的size合法性进行检查,所以我们把top_chunk的地址改了,就能申请任意地址
直接改top chunk的地址
申请一个size位为0x31的堆块,free掉,修改fd指针为0x61,再将这个堆块申请出来,这样main_arena中存储大小为0x30的堆块的数组就会存上0x61(为了伪造size位)

然后我们申请一个size位为0x61的堆块,free掉,修改指针到main_arena-80的地方这样,申请两次,将main_arena-80的堆块申请出来,因为main_arena-80与top chunk的地址紧挨着,所以可以写数据覆盖top chunk
为什么要是main_arena-80看图

这样可以伪造一个size位,堆块才能被申请在这里

具体写多少自己数
1 | add(0,0x20) |
3.fastbin dup consolidate
1 | #include <stdio.h> |
申请两个堆块大小范围在fastbin,p2是为了防止触发malloc_consolidate 使得p1被合并进入top_chunk
free掉p1进入fastbin申请0x400的大小的chunk,这时触发malloc_consolidate,p1就会被放在unsortbin
因为这时候p1已经不在fastbins了,可以再次free一次触发double free
这时候申请两次
第一次会把 fastbin 中的 p1 chunk 给 malloc 出来,然后 fastbin 为空
第二次会把 unsorted 中的 p1 chunk 给 malloc 出来,所以会能 malloc 到两次一样的 chunk
效果: 首先它会像unsortedbin(small)一样将相邻高地址的堆块inuse位置零同时也会被放进unsortedbin链表中(即存在fd和bk的使用), 其次它依旧满足fastbin的free堆块inuse位不置零, 那么如果存在有off by one或者其写入大小符合在不free时可以写入下一个chunk的pre_size, 那么就很容易触发到unlink了
具体实现:
malloc_consolidate的功能就是把chunk从fastbin取出,相邻的chunk进行合并,并且会设置下一个chunk的prev_inuse位为0。当chunk从fastbin里取出后,我们就可以在再一次free这个chunk了,此时,fastbin里没有形成循环链表,一个chunk在fastbin,一个chunk在unosrted bin(small)。关键的一点是下一个chunk的prev_inuse已经清零,我们将fastbin里的那个chunk申请回来,伪造一个chunk(往fastbin中写,也就是写入了unsortbin中,将fd与bk设为对应的值就可以),然后释放下一个unsorted bin范围的chunk,就会发生unlink。
1 | add(1,b'samll') |
触发unlink一定要伪造一个free掉的堆块在指针处,因为unlink比较是和头部比较,而数组中存储的是指针的值,所以要伪造头部在指针处才能绕过保护