通过 how2heap 复习堆利用 (三)
字数 2895 2025-08-20 18:18:17

堆利用技术详解:从基础到高级技巧

1. unsorted_bin_into_stack 技术

1.1 基本原理

通过改写 unsorted bin 中 chunk 的 bk 指针到任意地址,从而在栈上 malloc 出 chunk。

1.2 实现步骤

  1. 分配和释放 chunk

    • 分配一个 victim chunk (0x100)
    • 分配一个缓冲 chunk (0x100) 防止 victim 被合并到 top chunk
    • 释放 victim chunk 使其进入 unsorted bin
  2. 伪造栈上的 chunk

    stack_buffer[1] = 0x100 + 0x10;  // size 字段
    stack_buffer[3] = (intptr_t)stack_buffer;  // bk 指向自身
    
  3. 利用堆溢出修改 victim chunk

    • 修改 victim chunk 的 size 为 32 (绕过检查)
    • 修改 victim chunk 的 bk 指针指向伪造的栈 chunk
  4. 触发分配

    • 下一次 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 实现步骤

  1. 分配和释放 chunk

    • 分配两个 chunk,释放第一个使其进入 unsorted bin
  2. 利用堆溢出修改 bk 指针

    • 修改 chunk 的 bk 指针指向目标地址-2(相当于在目标地址处有一个 fake free chunk)
  3. 触发分配

    • 下一次 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 实现步骤

  1. 准备 fake chunk

    • 在目标地址(如栈上)构造一个 fake chunk
  2. 分配两个 chunk

    • chunk a (0x38)
    • chunk b (0xf8)
  3. 利用单字节溢出

    • 通过 chunk a 溢出修改 chunk b 的 size 字段,清除 PREV_IN_USE 位
    • 设置 chunk b 的 prev_size 为 fake chunk 到 chunk b 的偏移
  4. 释放 chunk b

    • 由于 PREV_IN_USE 为 0,系统会认为前一个 chunk 是 free 的
    • 根据 prev_size 找到 fake chunk 并合并
  5. 分配新 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 实现步骤

  1. 分配初始 chunk

    • malloc(0x400-16)
  2. 伪造 top chunk size

    • 通过堆溢出修改 top chunk 的 size 为较小的值 (如 0xc01)
    • 必须满足:
      • 对齐到内存页
      • 大于 MINSIZE(0x10)
      • 小于之后申请的 chunk size + MINSIZE(0x10)
      • prev_inuse 位为 1
  3. 分配大 chunk 触发 sysmalloc

    • malloc(0x1000) 会触发 top chunk 扩展
    • 原来的 top chunk 被放入 unsorted bin
  4. 利用 unsorted bin attack

    • 修改 unsorted bin 中 chunk 的 bk 为 _IO_list_all-0x10
    • 这会修改 _IO_list_all&unsorted_bin-0x10
  5. 伪造 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 字符串
  6. 触发异常处理

    • 分配一个很小的 chunk 触发 malloc_printerr
    • 最终会调用 _IO_OVERFLOW 即 system("/bin/sh")

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等)深入理解机制
堆利用技术详解:从基础到高级技巧 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 : 利用堆溢出修改 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 伪造 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") 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等)深入理解机制