阅读: 1
S7Comm全称S7 Communication ,是西门子为了多个PLC之间、SCADA与PLC之间的通信而设计的专属协议。在西门子S7-300 / 400系列、S7-200系列、S7-200 Smart系列上应用。S7-1200和S7-1500系列采用带有加密签名的S7CommPlus协议。
关于S7comm协议的解析有很多文章描述,但对该协议后期添加的Userdata部分的介绍较为匮乏,本文主要介绍S7Comm协议的Userdata部分的Read SZL子功能码的解析及其在安全产品中的应用。
S7Comm简介
S7Comm以太网协议基于OSI模型下表所示。
S7Comm协议的TCP/IP实现依赖于面向块的ISO传输服务,S7Comm协议被封装在TPKT和ISO-COTP协议中,这使得PDU(协议数据单元)能够通过TCP传送。
S7Comm PDU包含三个主要部分:
标头:包含长度信息,PDU参考和消息类型常量。
参数:内容和结构根据PDU的消息和功能类型有很大不同。
数据:这是一个可选字段,用于存储数据,例如内存值,块代码,固件数据等。
标头部分报文信息如下,包含了协议ID,消息类型,保留字段,PDU参考,参数长度,数据长度。其中有些报文中还包含了错误类(Error class)和错误代码(Error code)。
消息类型:PDU类型,一般有以下值:
- 0x01:JOB
即作业请求,如,读/写存储器,读/写块,启动/停止设备,设置通信。
- 0x02:ACK
即确认,这是一个没有数据的简单确认。
- 0x03:ACK_DATA
即确认数据的响应,一般是响应JOB的请求。
- 0x07:USERDATA
即扩展协议,其参数分段包含请求/响应ID,一般用于编程/调试,读取SZL等。
UserData类型介绍
当PDU类型为UserData时,S7Comm协议的结构如下图所示,S7Comm的参数部分为蓝色,展开描述为参数头3字节,参数长度1字节,方法字段1字节,类型字段半字节,功能组半字节,子功能码1字节,序号1字节。
常见的功能群组,如下表所示:
功能组代码 | 含义 |
0x0 | 转换工作模式(Mode-transition) |
0x1 | 工程师调试命令(Programmer commands) |
0x2 | 循环读取(Cyclic data) |
0x3 | 块功能(Block functions) |
0x4 | CPU功能(CPU functions) |
0x5 | 安全功能(Security) |
0x6 | 可编程块函数发送接收(PBC BSEND/BRECV) |
0x7 | 时间功能(Time functions) |
0xf | NC编程(NC programming) |
以下针对功能组中的0x4 CPU功能的子功能码如下表所示:
功能组代码 | 子功能码 | 含义 |
0x4 CPU功能 | 0x01 | 读系统状态列表(Read SZL) |
0x02 | 消息服务(Message service) | |
0x03 | 诊断消息(Diagnostic message) | |
0x05 | 显示ALARM | |
0x06 | 显示NOTIFY | |
0x07 | 锁定ALARM | |
0x08 | 取消锁定ALARM | |
0x09 | 显示SCAN | |
0x0b | 确认ALARM | |
0x0c | 确认显示ALARM | |
0x0d | 锁定显示ALARM | |
0x0e | 取消锁定显示ALARM | |
0x11 | 显示ALARM_SQ | |
0x12 | 显示ALARM_S | |
0x13 | 查询ALARM | |
0x16 | 显示NOTIFY |
Read SZL详解
系统状态列表(德语:System-ZustandsListen,英语:System Status Lists)用于描述PLC的当前状态,系统状态列表的内容只能读取不能修改。系列状态列表包含了如下信息:
- 系统数据
- 模块状态数据
- 模块诊断数据
- 模块诊断缓冲区信息
系统状态列表的请求报文结构,如下,其中header头与parameter部分与上文描述一致,parameter部分的功能组为0x4,子功能码为0x01,在此着重展示Data部分(黄色标识)。
系统状态列表的响应报文结构,如下:
以上报文结构中出现了SZL-ID字段,该字段标识每个状态列表部分的代码编号,利用该编号与紧接的SZL-index可索引出完整的列表或者摘录。SZL-ID由部分列表的编号、部分列表摘录编号和模块等级组成。结构如下图:
模块等级如下所示:
对于CPU模块从12~15bit填充的0000,因此后续对于CPU模块的SZL请求组装报文时该部分均为0。
部分列表摘录编号,该字段的含义取决于特定的系统状态列表,有的状态列表该字段为2#0001,有的为2#0000,也会出现2#1111,具体取决于读取的状态列表。
部分列表的编号,该字段表示要索引的系统状态列表,也可以理解为要读取的具体向导码。
下表列出了可能使用到的编号,该表中是一个合集,有的编号在具体的CPU模块中可能失效,如利用W#16#xy75 (Switched DP slaves in the H-system)访问普通的CPU模块是不成功的。
部分列表 | SZL-ID |
模块标识 (Module identification) | W#16#xy11 |
CPU特征 (CPU characteristics) | W#16#xy12 |
用户存储区 (User memory areas) | W#16#xy13 |
系统区域 (System areas) | W#16#xy14 |
块类型 (Block types) | W#16#xy15 |
组件标识(Component Identification) | W#16#xy1C |
中断状态 (Interrupt status) | W#16#xy22 |
运行状态(Modes status ) | W#16#xy24 |
过程映像分区和OB之间的分配 (Assignment between process image partitions and OBs) | W#16#xy25 |
通讯状态数据 (Communication status data) | W#16#xy32 |
H CPU组信息 (H CPU group information) | W#16#xy71 |
模块LED的状态 (Status of the module LEDs) | W#16#xy74 |
在H系统中切换的DP从站 (Switched DP slaves in the H-system) | W#16#xy75 |
DP主站的系统信息(DP Master System Information) | W#16#xy90 |
模块状态信息 (Module status information) | W#16#xy91 |
机架/站的状态信息( Rack / station status information) | W#16#xy92 |
机架/站的状态信息 ( Rack / station status information) | W#16#0x94 |
扩展DP主站/PROFINET IO系统信息 (Extended DP master system / PROFINET IO system information) | W#16#xy95 |
模块状态信息(PROFINET IO&PROFIBUS DP) Module status information | W#16#xy96 |
工具更换信息Tool changer information (PROFINET IO) | W#16#xy9C |
CPU的诊断缓冲区 (Diagnostic buffer of the CPU) | W#16#xyA0 |
模块诊断信息(数据记录 0)(Module diagnostic information) | W#16#00B1 |
模块诊断信息(数据记录 1)、地理地址 (Module diagnostic information geographical address) | W#16#00B2 |
模块诊断信息(数据记录 1)、逻辑地址 (Module diagnostic information logical address) | W#16#00B3 |
DP从站的诊断数据 (Diagnostic data of a DP slave) | W#16#00B4 |
在报文结构中也包含了SZL-index字段,该字段与SZL-ID配合索引到具体要读取的详细系统状态列表,可以理解为索引子编号或地址。该字段根据不同的SZL-ID有不同的取值,如W#16#0001,W#16#0000等。
以上将SZL的报文结构及其关键的字段SZL-ID和SZL-index做了介绍。接下来,结合实战练习,深入理解报文交互过程。选取经常使用的模块标识 、运行状态、CPU的诊断缓冲区状态列表介绍。
模块标识
配置如下SZL-ID和SZL-index可获取到不同的模块资产信息。
SZL-ID | SZL-index | 含义 |
W#16#0011 | 任意值 | 读取CPU模块全部信息(模块名称、硬件版本、固件版本等) |
W#16#0111 | W#16#0001 | 读取CPU模块订货号 |
W#16#0111 | W#16#0006 | 读取CPU模块基础硬件版本 |
W#16#0111 | W#16#0007 | 读取CPU模块固件版本 |
如下图为读取CPU全部信息的请求报文
响应报文中包含了CPU模块的所有信息:模块订货号6ES7 315-2EH14-0AB0(绿色框体内),模块固件版本V3.2.17(黄色框体),模块BootLoader版本37.12.12(蓝色框体)。
如下图为读取CPU订货号的请求报文,SZL-ID为0x0111,SZL-index为0x0001。
对应的响应报文如下,包含了订货号信息6ES7 315-2EH14-0AB0。
运行状态
配置如下SZL-ID和SZL-index可获取模块的运行状态信息,如模块当前处于RUN、STOP等状态。
如下图为读取CPU当前运行状态的请求报文,SZL-ID为0x0424,SZL-index为任意值均可,此处为0x0000。
对应的响应报文如下所示,在该时刻下CPU的运行状态为RUN,对应的代码为0x08,STOP运行状态对应的代码为0x03。
CPU诊断缓冲区
配置SZL-ID=0x00a0和SZL-index为任意值,可获取模块的诊断缓冲区信息,该处存放着模块的诊断事件和操作事件。
如下图为请求报文:
对应的响应报文如下所示,如若诊断缓冲区的内容较多,则CPU模块需要多次回应才可处理完成。响应报文中包含有事件总数,事件代码及其对应描述,事件发生时间戳。
以上仅列举了常用的几种类型的系统状态列表读取的报文分析,其余的状态列表还囊括了更大的信息量,比如SZL-ID为0x0232/SZL-index为0x0004时,为获取模块的保护级别,其中包含有密码信息。
Read SZL在安全产品中的应用
在工控安全产品中,有的产品需要对工业现场的设备做出识别,设备状态做出识别,这时候就需要针对不同厂商的设备及其资产做研究,利用何种方案去识别不同厂商的资产及状态。本文提出的S7Comm中Read SZL子功能码就可以解决针对S7-300/S7-400系列产品的这个问题,利用模块标识和运行状态对应的功能码字段可获取到资产信息及其资产运行状态;利用SZL列表中CPU诊断缓冲区功能码字段可读取资产的内部事件,可以作为资产健康度和资产审计使用;利用资产保护等级功能码字段可获取到设备的加密状态等。因此,SZL功能码的诞生对于做资产信息收集的产品来说无疑是一个福音,像是一个外部接口,只需要研究清楚接口调用就能轻松获取资产的信息。
是不是担心万一模块使用三级密码加密导致Read SZL功能不可用?此处回答:NO。S7-300/S7-400系列的密码为三级保护,设置了三级保护需要在读写时验证权限,但是对于SZL这种读取状态列表的操作功能则不需要。对于操作对象/功能/数据块之类就需要权限验证,如若权限不当则返回相应错误代码。
总结
本文对S7Comm协议中Userdata部分的Read SZL功能做了详细剖析,目的在于让这个显得极为复杂的但是又经常被我们使用的角色走向台前,让更多人的认识并了解它,在以后安全产品的预研及其设计过程中多一个思路,也可以让工控厂商在设计自己产品时学习‘老大哥’的这种做法,开放更多本体信息的接口,为正在走向我们的工业互联趋势做准备,有了这个接口,不仅可以获知资产信息、资产健康度,也可以与安全产品联动做到防护与控制相结合,做到安全生产,健康运营。