通过 how2heap 复习堆利用 (三)
字数 2895 2025-08-20 18:18:17
堆利用技术详解:从基础到高级技巧
1. unsorted_bin_into_stack 技术
1.1 基本原理
通过改写 unsorted bin 中 chunk 的 bk 指针到任意地址,从而在栈上 malloc 出 chunk。
1.2 实现步骤
-
分配和释放 chunk:
- 分配一个 victim chunk (0x100)
- 分配一个缓冲 chunk (0x100) 防止 victim 被合并到 top chunk
- 释放 victim chunk 使其进入 unsorted bin
-
伪造栈上的 chunk:
stack_buffer[1] = 0x100 + 0x10; // size 字段 stack_buffer[3] = (intptr_t)stack_buffer; // bk 指向自身 -
利用堆溢出修改 victim chunk:
- 修改 victim chunk 的 size 为 32 (绕过检查)
- 修改 victim chunk 的 bk 指针指向伪造的栈 chunk
-
触发分配:
- 下一次 malloc(0x100) 会从伪造的栈 chunk 中分配内存
1.3 关键点
- 需要绕过 size 检查:
2*SIZE_SZ (>16 on x64) && < av->system_mem - 伪造的 chunk 需要设置正确的 size 和 bk 指针
- 分配后,伪造 chunk 的 fd 指针会被修改为 unsorted bin 的地址,可用于泄露 libc 地址
2. unsorted_bin_attack 技术
2.1 基本原理
通过控制 unsorted bin chunk 的 bk 指针,向任意位置写入一个指针(通常是 unsorted bin 的地址)。
2.2 实现步骤
-
分配和释放 chunk:
- 分配两个 chunk,释放第一个使其进入 unsorted bin
-
利用堆溢出修改 bk 指针:
- 修改 chunk 的 bk 指针指向目标地址-2(相当于在目标地址处有一个 fake free chunk)
-
触发分配:
- 下一次 malloc 会执行 unlink 操作,将 unsorted bin 地址写入目标位置
2.3 关键点
- 主要用于信息泄露,为进一步攻击做准备
- 写入的地址是
&unsorted_bin-0x10 - 通常用于修改全局变量如
_IO_list_all,为后续攻击做准备
3. house_of_einherjar 技术
3.1 基本原理
利用单字节溢出漏洞修改 next chunk 的 size 字段并清除 PREV_IN_USE 标志,然后覆盖 prev_size 字段为 fake chunk 的大小,强制 malloc 返回一个几乎任意地址的 chunk。
3.2 实现步骤
-
准备 fake chunk:
- 在目标地址(如栈上)构造一个 fake chunk
-
分配两个 chunk:
- chunk a (0x38)
- chunk b (0xf8)
-
利用单字节溢出:
- 通过 chunk a 溢出修改 chunk b 的 size 字段,清除 PREV_IN_USE 位
- 设置 chunk b 的 prev_size 为 fake chunk 到 chunk b 的偏移
-
释放 chunk b:
- 由于 PREV_IN_USE 为 0,系统会认为前一个 chunk 是 free 的
- 根据 prev_size 找到 fake chunk 并合并
-
分配新 chunk:
- 下一次 malloc 会从 fake chunk 的位置分配内存
3.3 关键点
- 需要精确计算 fake chunk 的大小和位置
- 需要绕过 unlink 检查:
p->fd = p; p->bk = p - 可以用于将堆分配到栈或其它可写内存区域
4. house_of_orange 技术
4.1 基本原理
在没有 free 函数的情况下通过修改 top chunk 大小触发 sysmalloc,使原来的 top chunk 被释放并置入 unsorted bin 中。
4.2 实现步骤
-
分配初始 chunk:
- malloc(0x400-16)
-
伪造 top chunk size:
- 通过堆溢出修改 top chunk 的 size 为较小的值 (如 0xc01)
- 必须满足:
- 对齐到内存页
- 大于 MINSIZE(0x10)
- 小于之后申请的 chunk size + MINSIZE(0x10)
- prev_inuse 位为 1
-
分配大 chunk 触发 sysmalloc:
- malloc(0x1000) 会触发 top chunk 扩展
- 原来的 top chunk 被放入 unsorted bin
-
利用 unsorted bin attack:
- 修改 unsorted bin 中 chunk 的 bk 为
_IO_list_all-0x10 - 这会修改
_IO_list_all为&unsorted_bin-0x10
- 修改 unsorted bin 中 chunk 的 bk 为
-
伪造 IO_FILE 结构:
- 设置 size 为 0x61 使 chunk 被放入 smallbins[5]
- 伪造
_IO_FILE结构:_mode = 0_IO_write_base = (char *) 2_IO_write_ptr = (char *) 3
- 修改
_IO_jump_t中的__overflow为 system 地址 - 设置
/bin/sh字符串
-
触发异常处理:
- 分配一个很小的 chunk 触发
malloc_printerr - 最终会调用
_IO_OVERFLOW即 system("/bin/sh")
- 分配一个很小的 chunk 触发
4.3 关键点
- 需要精确控制 top chunk 的 size 字段
- 利用
_IO_FILE结构体进行控制流劫持 - 需要绕过多个检查:
fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base- smallbin 大小检查
- 是一种高级的堆利用技术,结合了多种技术
5. 总结与防御
5.1 技术总结
- unsorted_bin_into_stack: 通过修改 bk 指针在任意位置分配 chunk
- unsorted_bin_attack: 通过修改 bk 指针实现任意地址写
- house_of_einherjar: 利用单字节溢出和堆合并控制分配位置
- house_of_orange: 在没有 free 的情况下获取 free chunk 并利用 IO 结构体
5.2 防御措施
- 使用最新版本的 glibc(包含更多安全检查)
- 启用堆保护机制如 ASLR、FORTIFY_SOURCE
- 审计代码中的堆溢出漏洞
- 使用安全的堆分配器(如 hardened malloc)
5.3 学习建议
- 通过 how2heap 等资源实践这些技术
- 理解 glibc malloc 的底层实现
- 关注新版本 glibc 中的安全补丁和新增检查
- 结合源码分析(malloc.c、stdio-common等)深入理解机制