Large Bin
chunk size>0x400(0x40个机器字长)
large bin链表的个数为63个,被分为6组。每个bin里的chunk大小不用相等,但是在一定范围内。这也导致了LB chunk 与其他chunk的些许不同。
LIFO双链表
LB Chunk
被释放进Large Bin中的chunk,除了以前经常见到的prev_size、size、fd、bk之外,还具有fd_nextsize
和bk_nextsize
:
- fd_nextsize,bk_nextsize:只有chunk可先的时候才使用,不过用于较大的chunk(large chunk)
- fd_nextsize指向前一个与当前chunk大小不同的第一个空闲块,不包含bin的头指针
- bk_nextsize指向后一个与当前chunk大小不同的第一个空闲块,不包含bin的头指针
- 一般空闲的large chunk在fd的遍历顺序中,按照由大到小的顺序排列。这样可以避免在寻找合适chunk时挨个遍历
LB管理机制
我们通过一个样例直观感受一下large bin的管理机制
1 |
|
调试一下
1 | No.1===>0x602000 |
也就是说其结构是
图中从左往右的chunk直接都由fd链接,反之则由bk链接
可以看到对于相同大小的堆块,先释放的堆块为堆头;对于不同的堆块,大的在前
Manners of attack
总的来说存在两种攻击方式:
- 在申请largebin的过程中,伪造largebin的
bk_nextsize
,实现非预期内存申请。 - 在largebin插入的过程中,伪造largebin的
bk_nextsize
以及bk
,实现任意地址写堆地址。
Principle
非预期地址申请
申请largebin大小的chunk时是从最小的开始找起的,也就是通过bk_nextsize反向遍历双链表
1 | if ((victim = first (bin)) != bin &&(unsigned long) (victim->size) >= (unsigned long) (nb)) |
- fake
bk_nextsize
==> 非预期地址 - 构造好数据使得非预期地址通过unlink的检查
- 申请出非预期地址
绕过unlink
的检查:伪造的内存空间将fd
与bk
按照smallbinunlink
的利用方式设置,而将bk_nextsize
和fd_nextsize
设置成0,这样就不会对这两个字段进行操作了。
条件 能够修改free LB chunk
效果 申请出非预期地址
任意地址写堆地址
从UB取出chunk到LB时,
1 | ...//将largebin从unsorted bin中取下 |
很明显有两个漏洞点,都可以向任意地址写入victim地址(堆地址),类似于UB attack,我们可以覆盖global_max_fast,从而进行fastbin attack