3. 安全通信基础
模糊测试,圈里人常叫它 Fuzzing。说白了,就是给目标程序灌一堆「乱七八糟」的数据,看它会不会崩溃、挂掉、或者干出什么出格的事。我入行那会儿,Fuzzing 还是个挺「土」的活——写个脚本随机改几个字节就开跑。现在不一样了,工具链成熟得很,但核心思想没变:用异常输入触发异常行为。
你想想看,一个协议解析器,正常报文它肯定处理得妥妥当当。但你要是给它一个长度字段写死 0xFFFF、实际数据只有 10 个字节的畸形包呢?很多漏洞就是这么挖出来的。
3.1 模糊测试的核心原理
Fuzzing 的流程其实就三步:
- 生成测试用例——构造畸形或半畸形的输入数据
- 执行目标程序——把数据喂给被测对象
- 监控异常——看程序有没有崩溃、断言失败、内存泄漏
我在项目里遇到过最典型的场景:一个私有协议网关,厂商说「绝对稳定」。我拿 Boofuzz 跑了不到两小时,就崩了三次。原因?一个整数字段没做边界检查,传个负数直接写穿堆栈。嗯,这就是 Fuzzing 的价值——你永远不知道哪个「正常」的逻辑藏着「不正常」的漏洞。
3.2 三种测试类型:黑盒、白盒、灰盒
这三种类型,区别在于你对目标内部结构的了解程度。我按自己的理解给你捋一捋:
| 类型 | 对源码的依赖 | 覆盖率 | 典型场景 |
|---|---|---|---|
| 黑盒 Fuzzing | 完全不需要 | 低(靠运气) | 闭源协议、二进制固件 |
| 白盒 Fuzzing | 需要源码 + 插桩 | 高(路径导向) | 开源库、自研协议栈 |
| 灰盒 Fuzzing | 部分需要(如覆盖率反馈) | 中高(反馈驱动) | 大部分实战场景 |
黑盒:我最开始做 Fuzzing 就是黑盒。拿个串口抓包工具,把正常报文抓下来,然后随机改字节。效率低,但胜在通用——你不需要知道目标里面长什么样。
白盒:有源码的情况下,白盒 Fuzzing 威力巨大。AFL 就是典型代表,它通过插桩获取每条路径的覆盖信息,然后「聪明地」选择能探索新路径的输入。我曾经用 AFL 测过一个开源 TLS 库,三天挖出 7 个崩溃,其中两个是 CVE 级别的。
灰盒:这是我现在最常用的方式。没有完整源码,但可以通过二进制插桩(比如 Intel PT)拿到覆盖率反馈。说白了,就是「黑盒的操作 + 白盒的反馈」。效率介于两者之间,但适用面最广。
3.3 协议 Fuzzer 设计思路
设计一个协议 Fuzzer,核心就两条路:基于变异和基于生成。我分别说说。
3.3.1 基于变异(Mutation-Based)
拿一个「种子」文件,然后对它做各种「破坏」:
- 翻转比特(bit flip)
- 替换字节(byte substitution)
- 插入/删除数据块(block insert/delete)
- 修改长度字段(length field tampering)
我曾经遇到一个坑:一个协议报文里有 CRC 校验。我改了数据载荷,但没更新 CRC,结果目标直接丢弃了所有变异报文。后来我加了个「智能变异」——改完数据后自动重算校验字段。嗯,这招很管用。
# 一个简单的比特翻转示例(Python 伪代码)
def bit_flip(data, pos):
byte_idx = pos // 8
bit_idx = pos % 8
data[byte_idx] ^= (1 << bit_idx)
return data
3.3.2 基于生成(Generation-Based)
这种方式不依赖种子,而是根据协议规范「从零构造」报文。你需要先定义协议模板:
- 字段类型(整型、字符串、枚举)
- 字段长度(固定、可变、依赖其他字段)
- 字段约束(取值范围、校验规则)
Peach Fuzzer 就是基于生成的典型代表。它的 Pit 文件(XML 格式)定义了完整的协议结构。我当年测一个工控协议 Modbus TCP,就是用 Peach 写的模板,把功能码、寄存器地址、数据长度全部参数化,然后让工具自动组合。
3.4 常用框架对比
市面上 Fuzzing 框架很多,但真正经得起实战考验的,我重点说三个:AFL、Boofuzz、Peach Fuzzer。
| 特性 | AFL | Boofuzz | Peach Fuzzer |
|---|---|---|---|
| 类型 | 灰盒(插桩反馈) | 黑盒/灰盒 | 黑盒(基于生成) |
| 适用对象 | 本地二进制程序 | 网络协议、文件格式 | 复杂协议、工控/车联网 |
| 上手难度 | 中(需要编译插桩) | 低(Python 脚本) | 高(Pit 模板学习曲线陡) |
| 效率 | 极高(路径导向) | 中(变异策略较简单) | 中高(模板精细则效率高) |
| 社区活跃度 | 非常活跃 | 活跃 | 一般(商业版为主) |
AFL(American Fuzzy Lop):我个人的「白月光」。它用遗传算法 + 覆盖率反馈,自动探索程序路径。你只需要提供种子输入和编译插桩后的二进制,剩下的交给它。我曾经用 AFL 测一个 JSON 解析库,从 10 个种子开始,24 小时后覆盖了 85% 的代码路径。
Boofuzz:Sulley 的继承者,纯 Python 实现。我最喜欢它的「监控-恢复」机制——目标崩了,它能自动重启并继续测试。适合长时间跑协议 Fuzzing。我有个项目跑了整整一周,中间崩了 200 多次,Boofuzz 全自动处理了。
Peach Fuzzer:商业级工具,社区版功能受限。它的 Pit 模板非常强大,支持复杂的协议状态机。我测过一些车联网协议(比如 CAN 总线上的诊断协议),Peach 的「状态感知」能力是其他工具比不了的。但说实话,学习成本也高——我第一次写 Pit 模板花了整整两天。
3.5 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以把它当作 Fuzzing 入门的「地图」:
从这张图你能看到,Fuzzing 的「根」是核心原理,然后分支出测试类型、设计思路和常用框架。我个人建议你按这个顺序学:先理解原理,再选一个类型(灰盒优先),然后掌握一种设计思路(基于变异上手快),最后选一个框架深入实践。