S7comm协议解析
记录一下通过wireshark对S7comm协议的解析过程
S7协议介绍
S7comm(S7 通信)是西门子专有协议,可在西门子 S7-300/400 系列的可编程逻辑控制器 (PLC) 之间运行。
它用于 PLC 编程、PLC 之间的数据交换、从 SCADA(监控和数据采集)系统访问 PLC 数据以及诊断目的。
S7comm 数据作为 COTP 数据包的有效载荷出现。第一个字节总是 0x32 作为协议标识符。
要建立与 S7 PLC 的连接,有 3 个步骤:
1.通过 TCP 端口 102 连接到 PLC
2.在 ISO 层连接(COTP 连接请求)
3.在 S7comm 层连接(s7comm.param.func = 0xf0,Setup 通信)
步骤 1) 使用 PLC/CP 的 IP 地址。
步骤 2) 用作两个字节长度的目标 TSAP。目标 TSAP 的第一个字节编码通信类型(1=PG,2=OP)。目标 TSAP 的第二个字节编码机架和插槽号:这是 PLC CPU 的位置。插槽编号在位 0-4 中编码,机架编号在位 5-7 中编码。
步骤 3) 用于协商 S7comm 的具体细节(如 PDU 大小)。
S7抓包分析
TPKT协议
TPKT协议是一个传输服务协议,它为上层的COPT和下层TCP进行了过渡。我们常用的RDP协议(remote desktop protocol,windows的远程桌面协议)也是基于TPKT的,TPKT的默认TCP端口为102(RDP为3389),其实它本身为payload增加的数据并不多,主要就是以下几个:
- version,1byte,表明版本信息
- reserved,1byte,保留
- length,2byte,包括payload和这三部分在内的总长度
COTP
COTP协议的全称是Connection-Oriented Transport Protocol,即面向连接的传输协议,从这个名字就可以看出,它的传输必然是依赖于连接的,所以在传输数据前必然有类似TCP握手建立链接的操作。
这里wireshark为我们标注出了CR和CC,后面的COTP包都是DT,这里的CR和CC其实分别是connect request和connet confirm的,也就是建立连接的过程,之后连接建立成功后,发送DT包,也就是data,是在发送数据。
接下来我们看一下COTP的连接包:
第一部分:
包含:length、PDU type、DST reference、SRC reference
length :标识长度(但是length这个标识位不计入长度)
PDU type:标识类型,常见的值有:
- 0x01: ED Expedited Data,加急数据
- 0x02: EA Expedited Data Acknowledgement,加急数据确认
- 0x04: UD,用户数据
- 0x05: RJ Reject,拒绝
- 0x06: AK Data Acknowledgement,数据确认
- 0x07: ER TPDU Error,TPDU错误
- 0x08: DR Disconnect Request,断开请求
- 0x0C: DC Disconnect Confirm,断开确认
- 0x0D: CC Connect Confirm,连接确认
- 0x0E: CR Connect Request,连接请求
- 0x0F: DT Data,数据传输
DST reference: 目标标识
SRC reference:源标识
第二部分(option)
可以看到在wireshark中将这部分(1个byte拆成了前四位和后两位),其中:
- 前四位标识class,也就是标识类别
- 倒数第二位对应Extended formats,是否使用拓展样式
- 倒数第一位对应No explicit flow control,是否有明确的指定流控制
第三部分(parameter)
分为三部分:parameter code、parameter length、data,
parameter code:标识类型,主要有:
- 0xc0,tpdu的size,tpdu即传送协议数据单元,也就是传输的数据的大小
- 0xc1,src-tsap (源设备号)
- 0xc2,dst-tsap (同上)
parameter length:长度
data:对应数据
COPT功能包
可以看到COTP功能包的PDU type为0X0f,只有三部分:length,type,opt
以上便是TPKT和COTP协议的解析过程。
S7COMM
S7Comm数据作为COTP数据包的有效载荷,第一个字节总是0x32作为协议标识符。
S7Comm协议包含三部分:
- Header
- Parameter
- Data
根据实现的功能不同,S7comm协议的结构会有所不同
Header部分:
在Header中最重要的字段就是ROSCTR,它决定了后续参数的结构。ROSCTR的类型常见有以下值:
- 0x01 - JOB(Request: job with acknowledgement):作业请求。由主设备发送的请求(例如,读/写存储器,读/写块,启动/停止设备,设置通信);
- 0x02 - ACK(acknowledgement without additional field):确认响应,没有数据的简单确认(未遇到过由S7 300/400设备发送得);
- 0x03 - ACK_DATA(Response: acknowledgement with additional field):确认数据响应,这个一般都是响应JOB的请求;
- 0x07 - USERDATA:原始协议的扩展,参数字段包含请求/响应ID(用于编程/调试,读取SZL,安全功能,时间设置,循环读取...)
Parameter部分:
Parameter的第一个字段为function,根据Header中ROSCTR的类别和Parameter中function的不同,parameter的结构,目的也会有所不同。
下面根据不同的功能码(function的值)讲解parameter的字段的构成:
0XF0(建立通信)
建立通信在每个会话开始时被发送,然后可以交换任何其他消息。它用于协商ACK队列的大小和最大PDU长度,双方声明它们的支持值。ACK队列的长度决定了可以同时启动而不需要确认的并行作业的数量。PDU和队列长度字段都是大端。
当PDU类型为Job(ROSCTR的值为0x01),function为0xf0时,Paramter的结构为:
具体的Parameter结构,如下:
- 1 (Unsigned integer, 1 byte): Parameter part: Reserved byte in communication setup pdu,保留字节;
- 2 (Unsigned integer, 2 bytes): Max AmQ (parallel jobs with ack) calling;
- 3 (Unsigned integer, 2 bytes): Max AmQ (parallel jobs with ack) called;
- 4 (Unsigned integer, 2 bytes): Parameter part: Negotiate PDU length。协商PDU长度。
从响应包可以看出ack队列为1,PDU最大长度为240
(不同的function的值,parameter的结构不一样,以下只列出结构信息,不一一详述)
0x04(读取值)
当PDU类型为Job,function为0x04时,Parameter的结构为:
(今天暂时先写到这里吧)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构