HouseFuzz:面向 Linux 固件的服务感知灰盒模糊测试
一、背景与意义
背景
1.1 物联网固件安全威胁日趋严峻
- 路由器、网关、智能家居等设备广泛运行 Linux 固件,成为重要攻击面
- 固件中的漏洞难以人工发现,亟需自动化漏洞挖掘手段
1.2 模糊测试(Fuzzing)是主流漏洞挖掘手段
- 通过大量自动生成的输入触发程序异常,发现潜在漏洞
- 灰盒模糊测试(如 AFL)通过代码覆盖率反馈引导输入变异,效率较高
1.3 固件测试的核心难题:真机难以获得
- 固件运行依赖特定硬件,无法直接 fuzzing,必须依赖仿真环境
- 仿真准确度直接决定测试效果
目标
本文目标:设计一套专为 Linux 固件网络服务的服务感知灰盒模糊测试框架 HouseFuzz,解决以下核心问题:
- 更完整地识别固件中的网络服务(避免遗漏)
- 支持多进程协同的 fuzzing 反馈引导(而非仅监控单进程)
- 感知定制化服务协议语义约束,生成高质量测试用例
二、研究现状
2.1 已有灰盒固件模糊测试工作
| 方向 | 代表方法 | 核心特点 |
|---|---|---|
| 系统级仿真 | Firmadyne、FirmAE | 仿真整个系统,开销大 |
| 进程级仿真 | FirmAFL、EQUAFL、GREENHOUSE | 仅仿真单个目标进程,轻量 |
2.2 模糊测试阶段的现有方法
| 环节 | 现有方法 |
|---|---|
| 反馈引导 | 仅监控单进程代码覆盖率 |
| 测试用例生成 | 标准协议模板 + 随机变异 |
2.3 本文定位
本文在仿真层 基于 GREENHOUSE 扩展,重点创新在多进程模糊测试框架 和定制协议感知上
三、存在问题 / 挑战(动机)
3.1 核心动机案例:一个典型多进程跨服务漏洞
📷 【插图位置:图1 --- 多进程协作漏洞触发示例代码】
这个缓冲区溢出漏洞需要四步触发,跨越两个进程:
| 步骤 | 进程 | 行为 |
|---|---|---|
| ① 服务初始化 | ncc |
启动 mini_http,绑定网络端口等待请求 |
| ② 请求发送 | 攻击者 | 发送恶意 HTTP 数据包 |
| ③ 请求处理 | mini_http |
识别 .cpp 结尾请求,经 IPC 转发给 ncc |
| ④ 漏洞触发 | ncc |
ipc_handler 无长度限制地读取字符串 → 缓冲区溢出 |
关键观察: 若只盯着 mini_http,永远触发不了 ncc 中的漏洞。
3.2 三大挑战
挑战一:服务仿真不完整
- 基于白名单方法(如 GREENHOUSE):
ncc不在白名单 → 直接忽略 - 基于系统仿真(如 FirmAE):遇到异常/中断就停止,服务可能没起完
HouseFuzz 见解: 观察异常流程事件(崩溃/挂起)→ 定位异常代码 → 自动打补丁 → 重新仿真,遍历更多初始化流程
挑战二:多进程反馈引导缺失
- 现有工具仅以
mini_http的代码覆盖率为引导 ncc的执行路径完全被忽略 → 无法发现跨进程漏洞
HouseFuzz 见解: 设计用户空间多进程 fuzzing 框架,监控并合并所有服务相关进程的覆盖率,同时支持多进程漏洞检测
挑战三:定制协议语义约束被忽略
- 触发
ncc漏洞,输入必须同时满足:标准 HTTP 语法 +CCPact=set这类固件私有约束 - 现有方法随机变异,生成的输入在浅层校验即被拒绝
HouseFuzz 见解: 用 TDG(令牌依赖图) 建模定制协议,离线+在线推理 token 约束,生成语义更合理的测试用例
四、核心思路

输入:固件镜像 + 标准协议
↓
┌──────────────────────────────┐
│ ① 服务仿真模块(§5) │
│ 遍历初始化 → 识别网络服务 │
└──────────────┬───────────────┘
↓
┌──────────────────────────────┐
│ ② 多进程模糊测试框架(§6) │
│ 多进程覆盖率引导 │
│ 多进程漏洞判定器 │
└──────────────┬───────────────┘
↓
┌──────────────────────────────┐
│ ③ 服务协议引导 Fuzzing(§7)│
│ 离线+在线 TDG 推理 │
│ CFG + TDG 生成测试用例 │
└──────────────────────────────┘
两大核心亮点:
- 多进程代码覆盖率作为引导信号
- 令牌依赖图(TDG)感知定制协议约束
五、技术路线
本文技术贡献分为两大方向:① 服务仿真 (解决"测谁"的问题)和 ② 模糊测试(解决"怎么测"的问题)
▌贡献一:服务仿真模块(§5)
核心目标: 在 fuzzing 开始前,尽可能完整地识别并启动固件中所有相关网络服务进程
5.1.1 整体思路:分析系统初始化过程
固件启动时,init / preinit 程序会依次拉起各类进程,建立网络通道和 IPC 通道。HouseFuzz 的策略是:跑通整个初始化流程 → 从中识别哪些进程监听了网络、哪些进程存在 IPC 依赖。
5.1.2 系统初始化仿真:自动异常修复循环
尝试运行 init → 检测异常 → 定位异常代码 → NOP 打补丁 → 重新运行
循环终止条件(满足其一即退出):
- 无新异常
- 新补丁导致识别到的通道数减少 → 判定误报,回退上一轮结果
- 达到最大迭代次数
异常的四种类型与检测方式:

| 进程类别 | 异常类型 | 检测方式 |
|---|---|---|
| INIT 进程 | 中断(验证失败/内存错误) | 检测 exit() 或已知错误信号 |
| INIT 进程 | 挂起(如进入调试 shell) | 无其他异常则积极判定为挂起 |
| 非 INIT 进程 | 崩溃(致命错误) | 检测 SIGSEGV 等致命信号 |
| 非 INIT 进程 | 忙等(如死等网卡) | CPU 占用 ≥ 总时间的 1/3 |
异常处理细节:
- 分析异常进程的执行轨迹尾部定位异常代码(进程中止/循环处即为根源)
- 选取满足两个条件的函数执行 NOP 替换:① 被调函数体积不超过阈值;② 位于程序自身可执行段(非外部库)
鲁棒性保障(回退机制): 打补丁后若识别到的网络/IPC 通道数量反而减少 → 视为误报 → 自动回退,避免破坏正常初始化逻辑
5.1.3 面向网络的进程识别
动态追踪策略(非静态白名单):
- 全程记录系统调用轨迹(PID + 调用名 + 参数)
- 检查
bind()参数:绑定地址不是localhost→ 标记为面向网络进程 - 对 HTTPS 等加密隧道代理进程:基于已知端口(如 80)识别内层进程,直接对内层进程 fuzzing,绕过加密开销
- 从
execve()参数中提取完整命令行,用于后续独立仿真启动
5.1.4 守护进程识别
核心思路:顺藤摸瓜,通过 IPC 通道溯源
- 锁定通道"钥匙" :监控
open()/bind()记录 IPC 通道路径和文件描述符 - 追踪数据流 :监控
send()/recv(),发现 A 进程发出的数据被 B 进程读走 → 回溯 FD → 确认通道 - 判定守护进程 :若某进程建立的 IPC 通道被多个网络服务进程频繁读写 → 认定为守护进程(依赖项)
🔖 示例: GREENHOUSE 白名单中没有
zebra,因此无法识别它。但ripd服务的正常运行强依赖zebra守护进程。HouseFuzz 通过动态 IPC 分析,成功发现这一隐藏依赖并将zebra纳入测试范围。
5.1.5 进程仿真启动顺序
识别完成后,基于 GREENHOUSE 的进程仿真技术:
- 先启动守护进程
- 再启动面向网络的进程
- 两类进程均可按需自动拉起实用进程
所有由服务启动的子进程通过 execve() 系统调用追踪,纳入后续的覆盖率收集和漏洞检测。
▌贡献二:多进程模糊测试框架与测试用例生成(§6 + §7)
核心目标: 在正确识别服务的基础上,用多进程感知的方式进行 fuzzing,同时生成语义合理的测试用例
5.2.1 多进程覆盖率引导:TCE 检测
核心问题:多进程 fuzzing 中,何时才算"一次测试完成",可以收集覆盖率了?
单进程只需判断进程是否终止;多进程中,各进程生命周期不同,需要分别判断:
| 进程类型 | 特点 | TCE 判定方式 |
|---|---|---|
| 实用进程(短生命周期) | 处理单个请求即退出 | 进程终止 |
| 面向网络的进程(长驻) | 处理请求后继续运行 | 检测网络套接字被释放 |
| 守护进程(IPC 模式) | 处理完 IPC 后复用通道等待 | 检测重新调用 select/poll 等 I/O 监听调用 |
关键顺序约束: 先确认所有网络进程和实用进程的 TCE,再判定守护进程 TCE → 避免一次 test 中多轮 IPC 请求引发的误判
5.2.2 覆盖率记录与引导
记录机制:
- 进程启动时分配独立共享内存覆盖位图,避免多进程数据竞争
- 测试完成后位图归还共享内存池,供下次复用
- 守护进程维护激活标志 :退出
accept()后才开始记录,降低无效开销
引导机制:
- 将全部进程位图与历史覆盖率做 diff,任一进程出现新 bit → 种子有价值 → 入队
- 加载同一 ELF 文件的多个进程位图先合并(求和),再统一比较,保证跨 test 一致性
5.2.3 多进程漏洞检测
重点检测两类漏洞,覆盖所有服务进程(网络进程、守护进程、实用进程):
| 漏洞类型 | 检测方式 | 关键细节 |
|---|---|---|
| 内存损坏 | 检测所有进程的崩溃信号(如 SIGSEGV) | 通过输入可控性分析,过滤实用进程中不可利用的崩溃 |
| 命令注入 | 对所有进程 execve() 系统调用插桩 |
先用普通字母绕过过滤器探路,确认路径可达后再替换为注入字符串 |
🔖 设计亮点: 命令注入检测直接插桩
execve(),而非依赖厂商 API(厂商会对 API 做特殊处理),确保检测不被绕过。
5.2.4 服务协议引导的测试用例生成:协议形式化
问题根源: 仅靠 CFG 生成的输入格式正确,但语义可能不符合固件私有约束,在浅层就被拒绝。
解决方案:CFG(语法结构)+ TDG(语义约束)双层建模
| 概念 | 类比 | 作用 |
|---|---|---|
| CFG(上下文无关语法) | 作文的语法模板(主谓宾结构) | 保证输入格式正确(如合法的 HTTP 请求骨架) |
| TDG(令牌依赖图) | 逻辑关系图(主语是"老师"时谓语必须是"讲课") | 保证输入语义 合理(如 key 与 value 的搭配约束) |
TDG 定义: 有向图 G(N, E),节点为 token(类型:Path / Key / Value),边表示两类依赖关系:
- 控制流依赖:一个 token 决定另一个 token 是否会被访问(或走哪个分支)
- 数据流依赖:一个 token 决定另一个 token 如何被解释
5.2.5 三类 Token 依赖场景(理解 TDG 的关键)

| 场景 | 依赖类型 | 具体示例 |
|---|---|---|
| 场景1(开关型) | 控制流依赖 | action=set 存在时 value 才会被处理;action=get 时 value 根本不访问 |
| 场景2(分支型) | 控制流依赖 | type=network → 需要 ip、mask;type=system → 需要 timezone、hostname |
| 场景3(解释型) | 数据流依赖 | format=hex 决定 data=FF 按十六进制解析;format=string 则按字符串解析 |
核心启示: 不满足依赖关系的 token 组合,即使格式合法也会在浅层被拒绝,无法触达深层漏洞代码。
5.2.6 在线 TDG 推理(动态,边 fuzzing 边更新)
以 ccp_act=AAA 的 HTTP 请求为例:

输入:POST /get_set.cpp HTTP/1.1
ccp_act=AAA&...
| 步骤 | 操作 | 结果 |
|---|---|---|
| Step 1:收集 token | HTTP 解析器解析测试用例 | AAA→Value,ccp_act→Key,/get_set.cpp→Path |
| Step 2:推断新 token | 插桩 strcmp() 发现 strcmp("AAA","set") |
推断期望 token "set",类型同为 Value |
| Step 3:建立依赖 | Value 依赖同参数的 Key | TDG 新增边:"set" → "ccp_act" |
后续 fuzzing 若包含 Key ccp_act,就会优先尝试 Value "set",大幅提高通过浅层校验的概率。
5.2.7 离线 TDG 推理(静态,启动时预生成初始 TDG)
不依赖运行时数据,通过静态分析提前建图:
- 调用静态分析工具(IDA Pro)提取 URL 路径、参数键 → Path / Key token
- 基于控制流 / 数据流分析,识别图4中的三类代码模式 → 推断 token 依赖关系
- 在推断依赖过程中,顺带发现与常量字符串比较处的 Value token
- 整合为初始 TDG,弥补 fuzzing 早期缺乏种子覆盖的不足
在线 vs 离线互补:
| 离线组件 | 在线组件 | |
|---|---|---|
| 时机 | fuzzing 开始前 | fuzzing 过程中持续更新 |
| 优势 | 启动快,提供初始 TDG | 随探索深入不断完善 |
| 局限 | 只能识别标准字符串比较函数 | 还能识别定制化字符串比较逻辑 |
5.2.8 测试用例生成:CFG 骨架 + TDG 填充

两步生成流程:
- CFG 展开 :按语法规则生成合法请求骨架(如
⟨KV⟩ → ⟨Key⟩=⟨Value⟩) - TDG 填充:查询 TDG,按依赖关系插入语义合理的 token 值
🔖 示例对比:
- 传统方法(随机变异):
{"deviceType": "abc", "operation": "xyz"}→ 浅层拒绝- HouseFuzz(TDG 引导):查询 TDG →
deviceType=light时operation限定为toggle/dim→{"deviceType": "light", "operation": "toggle"}→ 通过校验,进入深层代码
六、实验评估
实验设置
- 工具链:Binwalk(固件提取)+ QEMU(仿真)+ Radare2(轨迹分析)+ IDA Pro(离线 TDG)+ AFL++(fuzzing)
- 数据集:60 个可用固件(3 个厂商,70 个原始镜像,10 个提取失败)
- 环境:Ubuntu 22.04,Intel Xeon Gold 5218,64 核,245 GB 内存
RQ1:整体性能对比(vs. GREENHOUSE)

| 指标 | GREENHOUSE | HouseFuzz | 提升 |
|---|---|---|---|
| 代码覆盖率(边覆盖) | 基线 | +24.8% | p < 0.01 |
| 发现漏洞数 | 46 个 | 128 个 | +178% |
| 其中 0-day 数 | 40 个 | 110 个 | +175% |
| 覆盖服务数 | 18 个 | 25 个 | --- |
最新固件验证 :在 2020 年后新固件数据集(12 个固件)中,额外发现 21 个 0-day,均已获 CVE/CNVD 编号
总漏洞披露: 共上报 156 个 0-day(58 个缓冲区溢出 + 15 个命令注入 + 83 个拒绝服务)
RQ2:服务识别效果

| 工具 | 识别面向网络进程数 | 召回率 |
|---|---|---|
| GREENHOUSE | 44 | 18.1% |
| FirmAE | 128 | 33.1% |
| HouseFuzz | 311 | 80.4% |
- 精确率均为 100%(人工确认)
- HouseFuzz 在 23 个额外固件上识别了 119 个(+37%)网络服务(来自异常修复)
- 发现 85 个仿真异常,8 个被回退机制正确识别为误报
RQ3:多进程框架消融实验

- HOUSEMP(多进程)在 16 个目标服务上代码覆盖率明显高于 GREENHOUSE(单进程)
- 多进程框架额外检测出 14 个 GREENHOUSE 无法发现的漏洞
- 共识别 24 个多进程漏洞 ,其中 17 个获 CVE/CNVD 编号(占全部编号漏洞的 38%)
- 53.7% 的目标服务存在 IPC 行为
TCE 稳定性: 8,746 个种子中,排除非确定性控制流(NCL)后,TCE 检测达到 100% 一致覆盖率
RQ4:协议引导消融实验
| 方案 | 发现漏洞数 |
|---|---|
| HOUSECFG(仅 CFG) | 36 |
| HOUSETDGOL(CFG + 在线 TDG) | +94% vs HOUSECFG |
| HOUSEFUZZ(CFG + 在线 + 离线 TDG) | 比 HOUSETDGOL 再多 55 个 |
TDG 推理质量:
- 平均每个 TDG 含 734 个节点、2610 条依赖边
- Token 推理精确率:HouseFuzz 62% vs GREENHOUSE 15%
- 依赖关系推理精确率:44%(即使不完全准确,fuzzing 试错机制可自动筛选)
七、总结与体会
7.1 论文贡献总结
| 模块 | 核心创新 | 效果 |
|---|---|---|
| 服务仿真 | 异常自动检测与修复循环 | 网络服务识别提升 76%+ |
| 多进程 Fuzzing | 全进程 TCE 检测 + 多进程覆盖率合并 | 发现 24 个跨进程漏洞(38% CVE) |
| 协议引导 | 离线+在线 TDG 推理 | 0-day 发现提升 175% |
7.2 主要局限
- 仿真保真度:仍基于进程仿真,非真实设备,存在覆盖盲区
- 认证后逻辑:缺少 session 维护,难测试需登录后才可访问的功能
- 未知协议:约 32.4% 服务使用非标准协议,协议引导能力有限
- TDG 精度:Token 和依赖推断仍有噪声(精确率 44%~62%)
- 适用范围:专为 Linux 固件网络服务设计,非通用嵌入式 fuzzing 框架
7.3 个人体会
- 项目提供了 Docker 镜像,本地(Win11 + Docker + QEMU)进行了简单复现尝试
- 虚拟机嵌套导致仿真较慢,资源消耗较高
- 模糊测试阶段需要提前通过 IDA 准备种子集,上手门槛相对较高
- 整体来看,多进程 fuzzing 框架是本文最有价值的创新点,弥补了现有工具对多进程协作漏洞检测的系统性缺失
📌 参考资料
- 论文:HouseFuzz: Service-Aware Grey-Box Fuzzing for Vulnerability Detection in Linux-Based Firmware
- 代码:https://github.com/HouseFuzz/HouseFuzz
- 对比基线:GREENHOUSE(https://github.com/sefcom/greenhouse)、FirmAE、FirmAFL