The Siemens S7 Communication - Part 2 Job Requests and Ack Data
本文系列深入介绍了西门子S7协议,第一部分详细阐述了通用通信场景和数据包结构,本部分进一步探讨了作业请求和确认数据消息的目的和内部结构。这些消息类型被放在一起讨论,因为它们非常相似,通常每一个作业请求都会导致确认数据回复。S7协议数据单元(PDU)和一般协议头的结构在之前的部分有解释。然而,参数头部是与消息类型特定的,针对作业和确认数据消息,它以功能代码开头。其余字段的结构取决于这个值。功能代码决定了消息的目的,并作为后续讨论的基础。
开始通信
[0xF0] Pcap: S300 SETUP COMMUNICATION
在每会话开始并且可以交换其他消息之前,此消息对(作业和确认数据响应)被执行,用于协商确认队列长度和最大PDU长度,双方声明支持的值。确认队列的长度决定了可以同时启动多少个并行作业而不需要确认。PDU和队列长度字段均以大端字节序表示。参数头部如下图所示:
S7验证与保护
[0x04/0x05] Pcaps: S300 AUTHENTICATION, S300 READ VARIABLE SIMPLE, S300 READ/WRITE VARIABLE (MULTIPLE VARIABLE READS AND WRITES WITH SIMPLE ADDRESSING) S400 READ/WRITE VARIABLE DB (MULTIPLE VARIABLE READS AND WRITES WITH DATABASE ADDRESSING)
变量读取和写入操作通过指定内存区域、地址(偏移)和大小或类型来执行。在深入探讨协议细节之前,我想简要介绍一下S7的地址模型。如同之前提到的,通过指定地址来访问变量。这个地址由三个主要属性组成:内存区域、符号名等。每个区域具有特定的访问权限和描述:
1. Merker: 包括任意标记变量或标志寄存器。
2. 数据块: 最常见的数据存储区域,模块中的数据以数据库形式存储并编号,是地址的一部分。
3. 输入: 数字和模拟输入模块值,映射到内存中。
4. 输出: 映射到内存中的输出。
5. 计数器: PLC程序中使用的计数器值。
6. 定时器: PLC程序中使用的定时器值。
地址X XXX 2.1 访问数据块 123 的第三字节中的第二个位。
读/写变量部分
在本节开始,事情变得复杂。强烈建议在阅读本节时查看提供的pcaps(Wireshark2默认启用S7分解器)。数据读取和写入操作通过指定内存区域、地址(偏移)和大小或类型来执行。在深入探讨协议细节之前,我请稍等,让我们稍作一个小的偏离,介绍S7的地址模型,如前面所述,变量通过指定地址访问,此次地址由三个主要属性组成:
1. 内存区域: 数据块(DB)地址DB区域,存储设备不同功能所需的数据,这些数据块编号,是地址的一部分。
2. 输入: 数字和模拟输入模块值,映射到内存中。
3. 输出: 映射到内存中的输出。
4. 计数器: PLC程序中使用的计数器值。
5. 定时器: PLC程序中使用的定时器值。
一般规则
在谈论S7安全性时,通用规则是:如果您可以ping设备,则可以控制它。在此处需要特别注意S71200/1500系列设备,它们采用稍有不同的方法,保护层处理略有不同,发送至设备的密码长度显著较长,但同样是常量和可重放的。
一般格式
为了激活程序块或更新工厂程序,并最终确保设备正确执行所需的步骤,需要执行特定的读取任务。这些步骤包括读取存储设备的块,然后设置相关的参数,如块类型(OB、DB、FC、FB等)和具体位置(如DB123.X、I123、Q123等)。首先引入了名为“预计功率”的块类型识别系统,通过将块分类为在执行期间需要的类型(例如,组织块、数据块、功能块等),提高了数据处理的效率。
要讨论的格式
该格式依赖于正在使用的指定方式(例如,可以是根据内存位置的描述性方式,或通过使用预定义符号名称来访问特定变量的简化方式),这在细节上将不会特别详述。完整的请求/数据项结构将根据访问方式的不同进行逐步介绍。
结论文本摘要
简而言之,虽然这是一个比预想更长的文章,但它可能对某些读者有帮助。S7协议设计并不优秀。最初,它只是用于查询寄存器值,功能逐渐增加,导致其复杂化成为一个庞大的系统。它充满了不一致性、冗余,并且用户数据消息(UDM)的引入进一步加剧了这些问题。在尝试解析这种协议时,这些不一致性和设计缺陷变得更加明显(令人烦恼)。
Tl;dr 如果使用S7比喻为一辆车,它可能看起来像这样……