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
题目特性
- 提供了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)处填充:
0x10 + p64(0) + p64(1)
这样设置可以:
- 提供正确的size值
- 设置prev_inuse位为1,避免合并检查
方法2:绕过检查
即使不衔接top chunk,只要确保:
- 下一个chunk的prev_inuse位为1
- 不触发合并检查
也能成功释放伪造的chunk。
总结
- 伪造unsorted bin chunk时,size字段和相邻chunk的prev_inuse位是关键
- 可以通过正确衔接top chunk或巧妙设置prev_inuse位来绕过检查
- 理解glibc的释放流程对于成功利用至关重要
- 在实际利用中,需要根据具体情况选择最合适的伪造方法
通过深入理解这些机制,可以更灵活地应对各种堆利用场景,提高漏洞利用的成功率。