【学习记录】Week12(一):House of Botcake——glibc 2.29+ 时代的堆重叠王者 写在前面在 glibc 2.29 版本中官方为 Tcache 引入了key字段用于检测并阻止经典的 Double Free 攻击。这一改动曾让许多习惯于利用 Tcache Double Free 制造堆重叠的选手极不适应。然而攻防博弈从未停止House of Botcake应运而生。它巧妙地利用了 Tcache 与 Unsorted Bin 之间的状态差异在不破坏任何校验机制的前提下完美实现了 Double Free 并制造堆重叠成为了现代 CTF (glibc 2.29 ~ 2.35) 必考的“基础设施”级技术。 目录背景回顾Tcache Key 机制与 Double Free 的困局核心破局House of Botcake 的状态错位思想详细的堆布局与利用流程推演实战进阶结合 Safe-Linking 的完整利用链总结与下篇预告1. 背景回顾Tcache Key 机制与 Double Free 的困局在 glibc 2.27 中Tcache 没有任何 Double Free 检查攻击者可以连续两次free同一个 chunk使其在 Tcache 链表中形成环A - A随后两次malloc即可实现任意地址写。为了修补这个漏洞glibc 2.29 在tcache_entry结构体中新增了key字段typedef struct tcache_entry { struct tcache_entry *next; struct tcache_perthread_struct *key; // 新增字段 } tcache_entry;当一个 chunk 被放入 Tcache 时堆管理器会在key字段写入一个特定的值当前 Tcache 结构体的地址。在执行free时如果发现该 chunk 的key等于这个特定值就会遍历当前的 Tcache 链表检查是否已存在该 chunk如果存在则触发free(): double free detected in tcache 2报错。这一机制直接封死了在 Tcache 中的直接 Double Free。2. 核心破局House of Botcake 的状态错位思想House of Botcake 的核心思想非常精妙如果一个 chunk 不在 Tcache 里而在 Unsorted Bin 里那么它的key字段就没有被设置。此时我们再次free它它就会顺利进入 Tcache这样一来这个 chunk 就同时存在于 Unsorted Bin双向链表和 Tcache单链表中。在 Unsorted Bin 中它的fd和bk指针指向main_arena中的地址我们可以利用这一点泄露 Libc 基址。在 Tcache 中我们可以通过 UAF 修改它的next指针实现Tcache Poisoning进而申请到任意地址。这就是 House of Botcake 的本质利用不同 Bin 机制的盲区实现状态的“双栖”。3. 详细的堆布局与利用流程推演假设题目环境为 glibc 2.31存在 UAF 漏洞且我们目标是利用大小为0x100的 chunk 制造重叠。步骤一填满 Tcache 并送入 Unsorted Bin分配 9 个大小为0x100的 chunkA, B, C, D, E, F, G, H, I。I用于防止后续释放时与 Top Chunk 合并。依次释放A到G。此时 Tcache[0x100]被填满7个。释放H。因为 Tcache 已满H进入Unsorted Bin。此时H的fd和bk指向main_arena96。关键点H的key字段没有被设置步骤二清空 Tcache 制造错位连续调用 7 次malloc(0xf8)将 Tcache[0x100]清空。再次释放G。此时 Tcache[0x100] 为空G顺利进入Tcache。步骤三触发 Double Free核心操作再次释放H。glibc 检查H的key字段发现它并不等于 Tcache 结构体地址因为它之前进的是 Unsorted Bin。检查通过H被放入Tcache。此时H同时存在于 Unsorted Bin 和 Tcache 中Tcache 链表状态head - H - G - NULL步骤四信息泄露与投毒泄露 Libc利用 UAF 漏洞读取H的fd指针。由于H同时在 Unsorted Bin它的fd指针存储着main_arena的地址。成功计算出 Libc 基址。Tcache Poisoning计算目标地址如__free_hook。利用 UAF 向H写入数据覆盖其在 Tcache 中的next指针为target_addr。*(注如果 glibc 2.32需结合 Safe-Linking 机制用泄露的堆地址异或目标地址)*。步骤五分配获取目标地址malloc(0xf8)- 返回H。malloc(0xf8)- 返回G。malloc(0xf8)-返回target_addr实现任意地址写。1. 填满 Tcache, 释放 H 进 Unsorted BinH 无 key2. 清空 Tcache3. 释放 G 进 Tcache4. 再次释放 H绕过 key 检查, H 进 Tcache5. H 同时在 Tcache 和 Unsorted Bin6. UAF 读 H 的 fd泄露 Libc7. UAF 写 H 的 next 指针实施 Tcache Poisoning8. 连续 Malloc 取出 H 和目标地址4. 实战进阶结合 Safe-Linking 的完整利用链在 glibc 2.32 环境中Tcache 引入了 Safe-Linking 机制next指针变成了(chunk_addr 12) ^ next_ptr。House of Botcake 如何与之适配泄露堆地址在步骤 4 中当我们向 Tcache 释放G时H此时还在 Unsorted Bin的fd指针被改写为 Tcache 加密后的G的地址。通过 UAF 读取这个值由于此时H是链表头next_ptr为 0所以加密后的值就是(H_addr 12) ^ 0 H_addr 12。我们成功泄露了堆地址的 key加密目标地址在步骤 8 中我们写入的next不能再是裸的target_addr而必须是(H_addr 12) ^ target_addr。由此可见House of Botcake 不仅能泄露 Libc还能顺带泄露堆地址简直是专为绕过现代防护量身定制的利器。5. 总结与下篇预告5.1 核心知识点总结本质利用 Unsorted Bin 中的 chunk 缺失 Tcachekey字段的特性进行跨 Bin 的 Double Free。效果让一个 chunk 同时存在于 Tcache 和 Unsorted Bin实现 Libc 泄露与 Tcache Poisoning 的双管齐下。地位在 glibc 2.29 环境中只要存在 UAF 且无其他严苛限制House of Botcake 几乎是制造堆重叠的首选方案。5.2 下篇预告在掌握了 House of Botcake 制造重叠和泄露的能力后下一篇我们将迎来本周的重头戏之一1.5天重点House of Pig。在 glibc 2.34 移除__free_hook等传统劫持点后House of Pig 将教我们如何将 Tcache Poisoning 与 IO_FILE (FSOP) 完美结合在失去 Hook 的时代依然能稳定 Getshell。结语House of Botcake 完美诠释了“魔高一尺道高一丈”的另一面——防御机制的缝隙总是存在的。掌握它你就拿到了通往现代堆利用大门的钥匙。