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协议的模型及其PDU类型。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等
当PDU类型为UserData时S7Comm协议的结构如下图所示,S7Comm的参数部分为蓝色,展开描述:参数头3字节,参数长度1字节,方法字段1字节,类型字段半字节,功能组半字节,子功能码1字节,序号1字节。 常见的功能群组,如下表所示 以下针对功能组中的0x4 CPU功能的子功能码如下表所示 以下进入到我们重点讲述的CPU功能码(0x4)中的0x01 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-index字段,该字段与SZL-ID配合索引到具体要读取的详细系统状态列表,可以理解为索引子编号或地址。该字段根据不同的SZL-ID有不同的取值,如W#16#0001,W#16#0000等。
以上将SZL的报文结构及其关键的字段SZL-ID和SZL-index做了介绍。接下来,结合实战练习,深入理解报文交互过程。选取经常使用的模块标识 、运行状态、CPU的诊断缓冲区状态列表介绍。
配置如下SZL-ID和SZL-index可获取到不同的模块资产信息。 如下图为读取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;
配置SZL-ID=0x00a0和SZL-index为任意值,可获取模块的诊断缓冲区信息,该处存放着模块的诊断事件和操作事件。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)