0x0 简介
这里总结一下堆里面安全性的检测和如何绕过
0x1 unlink
unlink 用来将一个双向链表(只存储空闲的 chunk)中的一个元素取出来,可能在以下地方使用
malloc
- 从恰好大小合适的 large bin 中获取 chunk。
- 这里需要注意的是 fastbin 与 small bin 就没有使用 unlink,这就是为什么漏洞会经常出现在它们这里的原因。
- 依次遍历处理 unsorted bin 时也没有使用 unlink 。
- 从比请求的 chunk 所在的 bin 大的 bin 中取 chunk。
- 从恰好大小合适的 large bin 中获取 chunk。
free
- 后向合并,合并物理相邻低地址空闲 chunk。
- 前向合并,合并物理相邻高地址空闲 chunk(除了 top chunk)。
malloc_consolidate
- 后向合并,合并物理相邻低地址空闲 chunk。
- 前向合并,合并物理相邻高地址空闲 chunk(除了 top chunk)。
realloc
- 前向扩展,合并物理相邻高地址空闲 chunk(除了 top chunk)。
源码
由于 unlink 使用非常频繁,所以 unlink 被实现为了一个宏,如下
总结下它的检测
1 | // 由于 P 已经在双向链表中,所以有两个地方记录其大小,所以检查一下其大小是否一致。 |
当需要unlink一个堆块时首先检测大小是否等于后一块的prev_size
1
2
3
4FD = P->fd; \
BK = P->bk; \
// 防止攻击者简单篡改空闲的 chunk 的 fd 与 bk 来实现任意写的效果。
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))接着检查unlink的堆块是否在链表中
0x2 _int_malloc
总结一下
1 | // 检查取到的 chunk 大小是否与相应的 fastbin 索引一致。 |
- 从fastbin中取出chunk后,检查size是否属于fastbin
1 | // 获取 small bin 中倒数第二个 chunk 。 |
- 从smallbin中除去chunk后,检查victim->bk->fd == victim
- 从unsortbin取chunk时,要检查2*sizet < 内存总分配量
- 从 largebin取chunk时,切分后的chunk要加入unsortedbin,需要检查 unsortedbin的第一个chunk的bk是否指向unsortedbin
- 如果freebin中有合适大小的堆块那么执行unlink操作
0x3 free
free的检查主要是根据本chunk的size检测下一块的inuse位,查看是否有double free的情况发生
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21mchunkptr old = *fb, old2;
unsigned int old_idx = ~0u;
do {
/* Check that the top of the bin is not the record we are going to
add
(i.e., double free). */
// so we can not double free one fastbin chunk
// 防止对 fast bin double free
if (__builtin_expect(old == p, 0)) {
errstr = "double free or corruption (fasttop)";
goto errout;
}
/* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been
deallocated. See use of OLD_IDX below for the actual check. */
if (have_lock && old != NULL)
old_idx = fastbin_index(chunksize(old));
p->fd = old2 = old;
} while ((old = catomic_compare_and_exchange_val_rel(fb, p, old2)) !=
old2);检查当前free的chunk是否与fastbin中的第一个chunk相同,相同则报错
根据当前的inuse以及后一块的后一块的inuse判断是否需要合并,如果需要合并则对在链表中的freebin进行unlink操作