fake_chunk与top chunk衔接的问题
字数 1778 2025-08-30 06:50:11

伪造unsorted bin与top chunk衔接问题详解

概述

在二进制安全领域,泄漏libc地址是常见需求,通常需要将chunk释放进入unsorted bin。但有些题目不会提供适合unsorted bin大小的chunk,这就需要修改原chunk的size字段或伪造size字段。然而,伪造size字段后,如果已分配的chunk不能正确衔接到top chunk,程序就会报错。

核心问题

伪造size字段后,需要在(伪造的chunk地址 + 修改后的size大小)这个地址处填充一个size值来衔接到top chunk。这个size值的计算公式为:

size值 = top chunk地址 - (伪造的chunk地址 + 修改后的size大小)地址

例题分析:[巅峰极客 2022]Gift

题目特性

  1. 提供了add、free、show功能以及一个后门函数bargain
  2. bargain函数只能修改next指针的低4个字节
  3. add函数只能申请10次,只能申请两种大小的chunk
  4. free函数存在UAF漏洞

利用思路

  1. 修改next指针指向堆上的伪造地址,在该地址处伪造一个unsorted bin chunk
  2. 释放该伪造chunk以获取libc地址
  3. 申请0x60大小的chunk(由于tcache中没有,会从unsorted bin中取),造成overlapping
  4. 修改next指针申请到__free_hook,填入one_gadget获取shell

关键点:size填充

正确填充方法

  1. 位置:伪造的chunk地址 + 伪造的size
  2. 大小:top chunk地址 - 前面计算得到的size填充的位置

常见错误分析

错误1:corrupted size vs. prev_size

当填充的size大小不合理(如0x30)时,free伪造的chunk会报错。错误发生在free+997地址处的比较指令:

  • r15寄存器通过free的chunk地址 + 其size地址得到
  • 程序会检查chunk的上一个chunk的prev_size字段是否与size值匹配

错误原因

程序通过以下方式判断chunk是否被释放:

  1. 根据chunk的上一个chunk的prev_inuse位来判断
  2. 如果判断为已释放,就会检查下一个chunk的prev_size字段值

解决方案

让程序判断chunk未被释放:

  • 将下一个chunk(相对于填充size的chunk)的prev_inuse位设置为1
  • 这样prev_size字段不会被启用

极端情况测试

即使将伪造chunk的size改为0x11,只要下一个chunk的prev_inuse位为1,也能正常free掉0x450大小的chunk。

unsorted bin释放流程详解

  1. 判断是否与top chunk相邻

    • 如果相邻,则直接回归top chunk
  2. 判断相邻chunk是否被释放

    • 对于低地址处的chunk:使用当前待释放chunk的prev_inuse位判断
    • 对于高地址处的chunk:使用"下下个chunk"(更高地址)的prev_inuse位判断
  3. 合并判断

    • 如果相邻chunk被释放,会进行合并操作(需对被释放chunk进行完整性检查)
    • 如果相邻chunk都未释放,则直接释放进入unsorted bin

伪造unsorted bin chunk的正确方法

要成功伪造并释放一个unsorted bin chunk,可以采取以下两种方式:

方法1:正确衔接top chunk

(伪造的chunk地址 + 伪造的chunk的size)处填充:

0x10 + p64(0) + p64(1)

这样设置可以:

  1. 提供正确的size值
  2. 设置prev_inuse位为1,避免合并检查

方法2:绕过检查

即使不衔接top chunk,只要确保:

  1. 下一个chunk的prev_inuse位为1
  2. 不触发合并检查

也能成功释放伪造的chunk。

总结

  1. 伪造unsorted bin chunk时,size字段和相邻chunk的prev_inuse位是关键
  2. 可以通过正确衔接top chunk或巧妙设置prev_inuse位来绕过检查
  3. 理解glibc的释放流程对于成功利用至关重要
  4. 在实际利用中,需要根据具体情况选择最合适的伪造方法

通过深入理解这些机制,可以更灵活地应对各种堆利用场景,提高漏洞利用的成功率。

伪造unsorted bin与top chunk衔接问题详解 概述 在二进制安全领域,泄漏libc地址是常见需求,通常需要将chunk释放进入unsorted bin。但有些题目不会提供适合unsorted bin大小的chunk,这就需要修改原chunk的size字段或伪造size字段。然而,伪造size字段后,如果已分配的chunk不能正确衔接到top chunk,程序就会报错。 核心问题 伪造size字段后,需要在 (伪造的chunk地址 + 修改后的size大小) 这个地址处填充一个size值来衔接到top chunk。这个size值的计算公式为: 例题分析:[ 巅峰极客 2022 ]Gift 题目特性 提供了add、free、show功能以及一个后门函数bargain bargain函数只能修改next指针的低4个字节 add函数只能申请10次,只能申请两种大小的chunk free函数存在UAF漏洞 利用思路 修改next指针指向堆上的伪造地址,在该地址处伪造一个unsorted bin chunk 释放该伪造chunk以获取libc地址 申请0x60大小的chunk(由于tcache中没有,会从unsorted bin中取),造成overlapping 修改next指针申请到 __free_hook ,填入one_ gadget获取shell 关键点:size填充 正确填充方法 位置 :伪造的chunk地址 + 伪造的size 大小 :top chunk地址 - 前面计算得到的size填充的位置 常见错误分析 错误1:corrupted size vs. prev_ size 当填充的size大小不合理(如0x30)时,free伪造的chunk会报错。错误发生在 free+997 地址处的比较指令: r15寄存器通过 free的chunk地址 + 其size地址 得到 程序会检查chunk的上一个chunk的prev_ size字段是否与size值匹配 错误原因 程序通过以下方式判断chunk是否被释放: 根据chunk的上一个chunk的prev_ inuse位来判断 如果判断为已释放,就会检查下一个chunk的prev_ size字段值 解决方案 让程序判断chunk未被释放: 将下一个chunk(相对于填充size的chunk)的prev_ inuse位设置为1 这样prev_ size字段不会被启用 极端情况测试 即使将伪造chunk的size改为0x11,只要下一个chunk的prev_ inuse位为1,也能正常free掉0x450大小的chunk。 unsorted bin释放流程详解 判断是否与top chunk相邻 : 如果相邻,则直接回归top chunk 判断相邻chunk是否被释放 : 对于低地址处的chunk:使用当前待释放chunk的prev_ inuse位判断 对于高地址处的chunk:使用"下下个chunk"(更高地址)的prev_ inuse位判断 合并判断 : 如果相邻chunk被释放,会进行合并操作(需对被释放chunk进行完整性检查) 如果相邻chunk都未释放,则直接释放进入unsorted bin 伪造unsorted bin chunk的正确方法 要成功伪造并释放一个unsorted bin chunk,可以采取以下两种方式: 方法1:正确衔接top chunk 在 (伪造的chunk地址 + 伪造的chunk的size) 处填充: 这样设置可以: 提供正确的size值 设置prev_ inuse位为1,避免合并检查 方法2:绕过检查 即使不衔接top chunk,只要确保: 下一个chunk的prev_ inuse位为1 不触发合并检查 也能成功释放伪造的chunk。 总结 伪造unsorted bin chunk时,size字段和相邻chunk的prev_ inuse位是关键 可以通过正确衔接top chunk或巧妙设置prev_ inuse位来绕过检查 理解glibc的释放流程对于成功利用至关重要 在实际利用中,需要根据具体情况选择最合适的伪造方法 通过深入理解这些机制,可以更灵活地应对各种堆利用场景,提高漏洞利用的成功率。