Tcache_perthread_corruption
参考资料:https://www.cnblogs.com/Theffth-blog/p/12790720.html
Tcache_perthread_corruption 概述
在堆题中,我们常见的一种泄露地址的方法是泄露 unsortedbin 中的 fd 和 bk 指针。而在严格限制 chunk 大小的堆题当中,如果有 Tcachebin 机制的影响,我们必须先将 Tcachebin 填满才能把释放的 chunk 放入 UnSortedbin 当中进行地址泄露 main_arena + 固定偏移。此时如果题目堆 malloc 和 free 的次数进行限制,我们就无法堆 Tcachebin 填充满,从而难以获取 UnSortedbin。
这个时候我们可以考虑伪造 Tcachebion 基址的 tcache_perthread_struct 结构体。
tcache_perthread_struct
1 | /* We overlay this structure on the user-data portion of a chunk when |
- 可以看到 tcache_perthread_struct 结构体首先是类型为 char(1 个字节)的 counts 数组,用于存放 64 个 bins 中 chunk 的数量,随后一次是对应 size 大小 0x20-0x410 的 64 个 entries(8 个字节),用于存放 64 个 bins 的 bin 的头地址
1. counts
它是一个数组,数组的每个元素对应一个特定大小的 Tcache 链表。
- 作用:记录对应链表中当前缓存了多少个空闲 chunk。本质上是一个整数
- 位置含义:counts[0] 对应大小为 0x20 的链表,counts[1] 对应 0x30……以此类推。counts[i] 的值为 0 到 7,表示对应链表里的 chunk 数量。
2. entries
它也是一个数组,每个元素是一个指针,指向对应大小链表的第一个空闲 chunk。
- 是每条 Tcache 单向链表的头指针。系统分配或回收 chunk 时,都是通过这个指针找到对应的链表。
- 类型:tcache_entry *,在 64 位系统下是 8 字节指针。
- 位置含义:entries[0] 指针指向大小为 0x20 的链表头部,entries[1] 指向大小为 0x30 的链表头部……如果某链表为空,对应的指针就是 NULL。
glibc 2.26-2.29
在早期的 glibc-2.26-2.29 版本中 tcache_perthread_struct 自身大小是 0x250。其 counts 元素类型为 uint8_t(1 字节),其结构体内容大小为 0x40(counts) + 0x200(entries),实际大小还要加上 chunk 头,是 0x250。
glibc 2.30 及以上
由于 counts 元素类型变为 unit16_t 成为了 2 字节大小,对应结构体也就变成了 0x80 + 0x200 + 0x10 = 0x290

1 | heap_base + 0x00 prev_size & size chunk_header |
a little demo
1 |
|



emmmm 结构体大概就是这么一回事儿,看看调试过程应该就可以理解。
更新: 2026-04-27 00:30:36
原文: https://www.yuque.com/idcm/wnemg9/yw8p14qr7wfoh8hz