高版本下tcache bin如何通过key值绕过double free
字数 1210 2025-08-22 18:37:22
Tcache Bin Double Free绕过技术分析
1. Tcache Entry结构分析
在libc 2.35中,进入tcache bin的chunk使用以下结构体:
typedef struct tcache_entry {
struct tcache_entry *next; // 指向下一个tcache entry的指针
uintptr_t key; // 用于检测double free的key值
} tcache_entry;
2. Tcache Put机制
当chunk被放入tcache bin时,会执行以下操作:
tcache_put(mchunkptr chunk, size_t tc_idx) {
tcache_entry *e = (tcache_entry *)chunk2mem(chunk);
// 标记这个chunk为"在tcache中",用于检测double free
e->key = tcache_key;
// 加密next指针
e->next = PROTECT_PTR(&e->next, tcache->entries[tc_idx]);
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
}
其中PROTECT_PTR宏定义为:
#define PROTECT_PTR(pos, ptr) \
((__typeof(ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
3. 堆地址泄露原理
当释放一个tcache chunk时:
- 如果它是对应tcache bin的第一个chunk,其next值为:
(chunk_mem_addr >> 12) ^ 0 - 由于地址按页(0x1000)对齐,右移12位后可以左移恢复大部分地址信息
4. Tcache Get机制
从tcache bin中取出chunk时:
tcache_entry *e = tcache->entries[tc_idx];
tcache->entries[tc_idx] = REVEAL_PTR(e->next);
--(tcache->counts[tc_idx]);
e->key = 0;
return (void *)e;
REVEAL_PTR宏定义为:
#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
5. Double Free检测机制
在_int_free函数中,有以下检测逻辑:
if (__glibc_unlikely(e->key == tcache_key)) {
tcache_entry *tmp;
size_t cnt = 0;
for (tmp = tcache->entries[tc_idx]; tmp; tmp = REVEAL_PTR(tmp->next), ++cnt) {
if (cnt >= mp_.tcache_count)
malloc_printerr("free(): too many chunks detected in tcache");
if (__glibc_unlikely(!aligned_OK(tmp)))
malloc_printerr("free(): unaligned chunk detected in tcache 2");
if (tmp == e)
malloc_printerr("free(): double free detected in tcache 2");
}
}
6. Double Free绕过技术
6.1 常规绕过方法
-
多指针记录法:
- 可以记录多个chunk指针且free后可以修改
- 构造A->B,然后修改A的next值为C,形成A->C
-
tcache填满法:
- 填满tcache bin使其进入fastbin
- 构造A->B->A的fastbin链
- 然后可以按需操作
6.2 单指针情况下的绕过
当只能记录一个chunk指针时,可以通过以下方法绕过:
- 关键思路:修改已释放chunk的key值
- 具体步骤:
- 第一次free(chunkA) - key被设置为tcache_key
- 修改chunkA的key值为其他值(如0)
- 再次free(chunkA) - 由于key != tcache_key,不会触发double free检测
- 此时chunkA被再次放入tcache bin
6.3 绕过原理分析
检测逻辑if (e->key == tcache_key)是关键:
- 第一次free后,key被设为tcache_key
- 如果修改key值,第二次free时检测条件不成立
- 因此不会进入遍历检查的循环,也就不会发现double free
7. 防御措施分析
当前tcache的防御机制:
- key值检测 - 可被修改绕过
- 链表遍历检测 - 依赖key值检测
- 指针加密 - 增加利用难度但不防止double free
8. 利用场景
这种绕过技术在以下场景特别有用:
- 只能控制有限数量指针的情况
- 存在UAF漏洞可以修改已释放chunk的内容
- tcache bin未填满无法进入fastbin的情况
9. 总结
高版本glibc中tcache的double free防护主要依赖key值检查,通过修改已释放chunk的key值可以有效地绕过这一防护机制。理解这一技术需要对tcache的内部结构和工作原理有深入认识,特别是key值的作用和PROTECT_PTR/REVEAL_PTR的指针加密机制。