本项目采用「VibeFuzzing」模式:由 DeepSeek 构造一个采用冷门且结构复杂工控协议的服务端靶子,
阅读 7884 引擎《使用说明.TXT》掌握方法论后,调用 7884_brain.exe NetGen 模式对该服务端执行在线协议模糊测试,
并对发现的崩溃进行归纳分析。测试遵循铁律:网络协议 Fuzz 一律使用 --engine pro(55 种变异策略 + 结构保护 + 字段感知)。
FINS(Factory Interface Network Service)为欧姆龙(OMRON)工厂自动化网络协议,
广泛用于 PLC 与上位机通信,属冷门、字段结构复杂的工控协议。标准承载于 UDP/TCP 9600 端口。
+------+------+------+------+------+------+------+------+------+------+--------+----------------+ | ICF | RSV | GCT | DNA | DA1 | DA2 | SNA | SA1 | SA2 | SID | CMD | DATA(变长) | | 1B | 1B | 1B | 1B | 1B | 1B | 1B | 1B | 1B | 1B | 2B | | +------+------+------+------+------+------+------+------+------+------+--------+----------------+ 帧头 10 字节 命令码(大端) 命令参数/数据
示例:80 00 02 00 01 00 00 01 00 01 | 0101 | 82 0000 0002(读 CIO 区 2 字)
模拟 PLC 内存区(DM/CIO 等 8 类区),实现内存区读/写、运行、节点数据读等命令分发,
异常处理路径视为进程级崩溃(命中后记录原始报文并立即退出,可被 process-alive 监视器捕获)。
| ID | 触发命令 | 漏洞类型 | 异常 |
|---|---|---|---|
| BUG-01 | 0x5B00 | 除零 DoS | ZeroDivisionError |
| BUG-02 | 0x0101 | 输入校验缺失 | KeyError |
| BUG-03 | 0x0101 | 越界读 | IndexError |
| BUG-04 | 0x0102 | 长度校验缺失 | struct.error |
| BUG-05 | 0x0102 | 越界写 | IndexError |
| BUG-06 | 0x0401 | 递归耗尽 | RecursionError |
| BUG-07 | 0x2301 | 转换异常 | UnicodeDecodeError |
依据《使用说明.TXT》第四、五部分,本测试执行了两条能力链路:
> 7884_brain.exe --NetGen out\xml\fins_net.xml --engine pro -i 30000 --host 127.0.0.1 --port 9600 [*] DataModel count: 2 [*] StateModel: Main (initial=S1) [*] Publisher: tcp-client 127.0.0.1:9600 [*] Iterations: 30000, timeout: 2000 ms [*] Engine: pro [!] MONITOR: target process died at iteration N iterations run / total sends / total recvs / timeouts / MONITOR: target process crashed
命令分发 XML:out\xml\fins_net.xml(通用)+ 4 个命令定向变体
fins_net_0102/0401/2301/5B00.xml。崩溃判定以 stdout 汇总行 MONITOR: target process crashed 为准;
stderr 的 [NetState] 行仅作过程噪音,不参与统计。
> 7884_brain.exe -i out\samples\req_only -o out\samples\output --cpu-threads 8 Analysis completed successfully! [Threads: 20, Time: 0m 4s] quality_overall = 0.9124 (CONVERGED) coverage = 1.0 > 7884_brain.exe --fast -m trained_model.model -s req_01.bin --script net [ResultGen] Generated <7884-net> XML: net_schema.xml > 7884_brain.exe --NetGen net_schema.xml --engine pro -i 10000 --host 127.0.0.1 --port 9600 [!] MONITOR: target process died at iteration 342 → BUG-02
引擎仅凭 8 个未知样本自动归纳出 FINS 结构(104 字段、580 关系、overall 0.912 收敛), 并自动生成协议 Fuzz 脚本,闭环命中真实崩溃——验证了"抓包样本 → 自动归纳 → 在线 fuzz"全自动能力。
| 会话组 | XML | 轮次 | 命中命令 | 崩溃类型 |
|---|---|---|---|---|
| 通用 0101 定向(12 轮) | fins_net.xml | round1-12 | 0x0101 | BUG-02 KeyError ×5 / BUG-03 IndexError ×7 |
| 0102 写命令(4 轮) | fins_net_0102.xml | cmd0102_1-4 | 0x0102 | BUG-05 IndexError ×2 / BUG-04 struct.error ×2 |
| 0401 嵌套命令(4 轮) | fins_net_0401.xml | cmd0401_1-4 | 0x0401 | BUG-06 RecursionError ×4 |
| 2301 节点读(4 轮) | fins_net_2301.xml | cmd2301_1-4 | 0x2301 | BUG-07 UnicodeDecode ×4 |
| 5B00 畸形命令(4 轮) | fins_net_5B00.xml | cmd5B00_1-4 | 跨命令 | BUG-01 / BUG-02 / BUG-04 / BUG-07 各 1 |
| 归纳闭环(1 轮) | net_schema.xml(自动生成) | autogen | 0x0101 | BUG-02 KeyError ×1 |
29 个 Fuzz 会话全部命中崩溃(每次崩溃后重启靶子继续下一轮)。总发包 1443,平均每会话约 50 次迭代即触发崩溃,验证了 pro 引擎的字段感知变异效率。
| ID | 命令 | 漏洞类别 | 异常类型 | 触发条件 | 命中 | CVSS 语义 |
|---|---|---|---|---|---|---|
| BUG-01 | 0x5B00 | 除零拒绝服务 | ZeroDivisionError | data 前 2 字节为 0x0000,做除数 | 1 | DoS(未授权崩溃) |
| BUG-02 | 0x0101 | 枚举校验缺失 | KeyError | 内存区码不在合法集合(0x82/0x89…) | 7 | DoS / 逻辑缺陷 |
| BUG-03 | 0x0101 | 越界读 | IndexError | 起始地址 + 数量 超出内存区容量(如 addr=0xD400, CIO 仅 6144 字) | 8 | 信息泄漏 / 崩溃 |
| BUG-04 | 0x0102 | 长度校验缺失 | struct.error | 声明 count 对应数据长度 > 实际接收数据(如 count=65304, 仅 679 字节可用) | 3 | DoS / 堆破坏前置 |
| BUG-05 | 0x0102 | 越界写 | IndexError | addr+count 超出内存区容量,写入越界 | 2 | 内存破坏(高危) |
| BUG-06 | 0x0401 | 递归耗尽 | RecursionError | 声明嵌套深度字段过大(如 0x0FFF),递归超出栈上限 | 4 | 栈溢出 / DoS |
| BUG-07 | 0x2301 | 数据转换异常 | UnicodeDecodeError / ValueError | data 区含非 ASCII 字节或非纯数字,直接 decode/int 转换 | 5 | DoS / 输入校验缺陷 |
# BUG-03 越界读(0x0101, addr=0xD400 超出 CIO 区) 80 00 02 00 01 00 00 01 00 01 01 01 82 d4 00 00 02 ... # BUG-04 解包失败(0x0102, count=0xFF18 数据不足) 80 00 02 00 01 00 00 01 00 01 01 02 89 ff ff 18 ff 1e 56 ... # BUG-01 除零(0x5B00, divisor=0x0000) 80 00 02 00 01 00 00 01 00 01 5b 00 00 00 ...
全部原始崩溃样本已归档:out\crashes\*.bin(30 个,含触发帧);靶子崩溃目录亦保留现场。
addr+count ≤ capacity。len(data) == count*2,不足即回长度错误码。