4. 协议报文结构解析
工业协议流量识别的第一步,不是看端口号,而是看报文本身。端口可以改、可以复用,但报文的帧结构、功能码语义、地址空间布局和数据编码方式,是协议最稳定的“指纹”。本节围绕 Modbus TCP、S7comm、EtherNet/IP 与 CIP 三类典型协议,拆解从字节到语义的解析路径,帮助你在流量分析中快速定位“这是什么协议、在做什么操作、操作了哪个对象”。
一、核心原理:四层解析模型
工业协议报文解析可以抽象为四层递进模型。第一层是帧格式,确定报文的起止边界与长度字段,解决“一个完整报文从哪里开始、到哪里结束”。第二层是功能码,确定请求/响应的操作类型,解决“这条报文想干什么”。第三层是地址空间,确定操作对象在设备中的位置,解决“操作的是哪个寄存器、哪个变量”。第四层是数据编码,确定字节序、数据类型与量纲,解决“读到的值到底是多少”。
这四层在流量识别中的价值不同:帧格式用于协议分类,功能码用于行为识别,地址空间用于资产建模,数据编码用于异常判定。例如,同样是写操作,写线圈和写保持寄存器的安全含义完全不同;同样是 4 字节,大端和小端解析出的数值可能相差 256 倍。
二、典型协议帧格式对照
不同工业协议的封装差异很大,但都可以用“头部 + 协议数据单元”来理解。Modbus TCP 的 MBAP 头固定 7 字节,其中长度字段表示后续字节数,是切分报文的关键。S7comm 运行在 TPKT 与 COTP 之上,需要先剥掉 4 字节 TPKT 和 COTP 头,才能看到 S7 的 ROSCTR 与功能码。EtherNet/IP 则使用封装头携带会话句柄和命令码,CIP 服务再嵌套其中。
| 协议 | 关键头部字段 | 典型功能码/服务 | 地址空间 | 数据编码要点 |
|---|---|---|---|---|
| Modbus TCP | 事务ID、协议ID、长度、单元ID | 0x01 读线圈、0x03 读保持、0x10 写多寄存器 | 0x/1x/3x/4x 四区,偏移从 0 起 | 大端;寄存器 16 位;32 位需高低字组合 |
| S7comm | TPKT 长度、COTP、ROSCTR、PDU 参考 | 0x04 读变量、0x05 写变量、0x1A 请求下载 | DB 块、I/Q/M 区、字节偏移 | 大端;位/字节/字/双字;DB 号需单独解析 |
| EtherNet/IP + CIP | 命令码、长度、会话句柄、状态 | 0x4C 读标签、0x52 写标签、0x6B 读数据 | 类/实例/属性;标签名寻址 | 小端为主;CIP 数据类型显式声明 |
三、方法流程:从抓包到语义还原
- 定位流:按五元组聚合会话,观察请求/响应配对关系,排除重传与心跳。
- 切分帧:依据长度字段或固定头长度,把 TCP 字节流还原为独立 PDU。
- 识别协议:检查 MBAP 协议ID是否为 0、TPKT 版本是否为 3、EtherNet/IP 命令码是否合法。
- 解析功能码:提取功能码/服务码,判断读、写、诊断、下载等操作类型。
- 还原地址:解析起始地址与数量,映射到设备变量表或资产模型。
- 解码数值:按字节序与数据类型还原工程值,必要时应用缩放系数。
modbus.func_code == 16、s7comm.param.func == 0x05、enip.command == 0x6f 等显示过滤器快速定位目标操作,再结合 tcp.stream eq N 跟踪完整会话。
四、案例场景:一次异常写操作的识别
某产线监控中发现一条 Modbus TCP 写操作,目标单元 ID 为 1,功能码 0x10,起始地址 40001,写入数量 2,数据为 0x00 0x64 0x00 0x00。解析过程如下:MBAP 头确认协议ID为 0,长度字段为 13,说明后续 13 字节有效;功能码 0x10 表示写多个保持寄存器;地址 40001 对应保持寄存器区第一个寄存器;数据大端解析为 100 和 0。结合工艺映射,该寄存器为“设定转速”,正常范围 0~50,写入 100 明显越界,触发异常告警。
原始字节(十六进制):
00 01 00 00 00 0D 01 10 00 00 00 02 04 00 64 00 00
字段解析:
事务ID = 0x0001
协议ID = 0x0000 → Modbus
长度 = 0x000D → 后续 13 字节
单元ID = 0x01
功能码 = 0x10 → 写多个保持寄存器
起始地址 = 0x0000 → 40001
寄存器数 = 0x0002
字节数 = 0x04
数据 = 00 64 00 00 → 100, 0(大端)
五、常见误区与复盘
- 误区一:只看端口判协议。502 端口可能承载非 Modbus 流量,S7 也可能跑在非 102 端口,必须校验头部特征。
- 误区二:忽略长度字段。不按长度切分会导致粘包,后续功能码和地址全部错位。
- 误区三:地址从 1 开始计数。Modbus 报文中的地址从 0 开始,而文档常写 40001,解析时需减 1。
- 误区四:字节序想当然。Modbus 与 S7 为大端,EtherNet/IP 多为小端,32 位浮点还涉及高低字交换。
- 误区五:功能码与地址空间脱节。0x01 只能操作线圈区,若地址落在保持寄存器区,说明报文构造异常或存在攻击行为。