The Siemens S7 Communication - Part 1 General Structure

I have been working with Siemens PLCs for quite some time, mostly developing applications that either communicate with them or observe/simulate their communication. I thought it would be time to share my gathered knowledge of the S7 protocol as some might find it useful, interesting. The purpose of this writing is to aid those who wish to gain a deeper understanding of the Siemens S7 communication protocol and help the development of software interfering with these devices. This documentation of the protocol is not comprehensive, there are many parts left to be uncovered. While writing this article I only had access to S-300 and S-400 series devices (S315-2A and S417 to be specific) and I had never worked with S-200/S-1200/S-1500 series PLCs before, thus functions specific to those are not covered here.

As far as I know, there is no publicly available documentation for the S7 protocol, however there are a few notable projects that help to deal with it. Davide Nardella has created a fantastic open source communication library the Snap7, which implements basic communication scenarios. The library comes with the extensive documentation of the basic structure of the S7 protocol. Another great project is the S7 Wireshark dissector by Thomas W. which covers most of the protocol and its source code contains a lengthy list of protocol constants. These proved to be invaluable for me during the years I have spent working with Siemens equipment. Since, there is no official documentation, official terminology does not exists when it comes to the S7 protocol. In the rest of this document I try to comply with the terms used in the above mentioned projects.

Edit: Since I wrote this article I learned about a new and actively developed open-source project, plc4x. The project provides implementation for multiple industrial protocols including the S7 protocol.

1. The Siemens Communication Scenario

Before going into more technical details first I’d like to briefly introduce the basic Siemens communication theater. When I talk about the “S7 protocol” I refer to the Ethernet S7 communication that is mainly used to connect the PLCs to the (I)PC stations (PG/PC - PLC communication). This is not to be confused with the different fieldbus protocols that the Siemens equipment use, such as MPI, Profibus, IE and Profinet (which is an Ethernet based protocol used to connect PLCs to IO modules, not the management protocol of the devices).

Most of the time the Siemens communication follows the traditional master-slave or client-server model, where the PC (master/client) sends S7 requests to the field device (slave/server). These requests are used to query from or send data to the device or issue certain commands. There are a few exceptions when a PLC can be the communication master, with FB14/FB15 the device can initiate GET and PUT requests to other devices.

In the S400 series a so called Cyclic Data I/O function is implemented, this resembles to the traditional publisher-subscriber model. The PC can subscribe to certain events, than the PLC periodically pushes the requested data to the network. There is also a Partner or peer-to-peer model, when an Active Partner requests a connection and calls Block Send while at the same time the Passive Partner calls the Block Receive method.

For more information on the general overview of the S7 communication see the Siemens Simatic Net and Snap7 documentation.

2. The S7 PDU

The S7 protocol TCP/IP implementation relies on the block oriented ISO transport service. The S7 protocol is wrapped in the TPKT and ISO-COTP protocols, which allows the PDU (Protocol Data Unit) to be carried over TCP. The ISO over TCP communication is defined in RFC1006, the ISO-COTP is defined in RFC2126 which is based on the ISO 8073 protocol (RFC905).This structure is presented in the figure below.

S7ProtoStructure

The S7 protocol is function/command oriented which means a transmission consist of an S7 request and an appropriate reply (with very few exceptions). The number of the parallel transmission and the maximum length of a PDU is negotiated during the connection setup.

The S7 PDU consists of three main parts:

  • Header: contains length information, PDU reference and message type constant
  • Parameters: the content and structure greatly varies based on the message and function type of the PDU
  • Data: it is an optional field to carry the data if there is any, e.g. memory values, block code, firmware data …etc.

2.1 Header

The header is 10-12 bytes long, the Acknowledgement messages contain two extra error code bytes. Other than that the header format is consistent across all the PDUs.

S7HeaderStructure

Fields:

  • Protocol ID:[1b] protocol constant always set to 0x32
  • Message Type:[1b] the general type of the message (sometimes referred as ROSCTR type)
    • 0x01-Job Request: request sent by the master (e.g. read/write memory, read/write blocks, start/stop device, setup communication)
    • 0x02-Ack: simple acknowledgement sent by the slave with no data field (I have never seen it sent by the S300/S400 devices)
    • 0x03-Ack-Data: acknowledgement with optional data field, contains the reply to a job request
    • 0x07-Userdata: an extension of the original protocol, the parameter field contains the request/response id, (used for programming/debugging, SZL reads, security functions, time setup, cyclic read..)
  • Reserved:[2b] always set to 0x0000 (but probably ignored)
  • PDU reference:[2b] generated by the master, incremented with each new transmission, used to link responses to their requests, Little-Endian (note: this is the behaviour of WinCC, Step7, and other Siemens programs, it could probably be randomly generated, the PLC just copies it to the reply)
  • Parameter Length:[2b] the length of the parameter field, Big-Endian
  • Data Length:[2b] the length of the data field, Big-Endian
  • (Error class):[1b] only present in the Ack-Data messages, the possible error constants are listed in the constants.txt
  • (Error code):[1b] only present in the Ack-Data messages, the possible error constants are listed in the constants.txt

The rest of the message greatly depends on the Message Type and function code I will be covering each of those in the upcoming articles. Part 2 will focus on Job Requests and Ack-Data messages. Part 3 will cover the different **Userdata** functions and their structures.

All the different protocol constants are collected in the constants.txt.

I plan to keep these writings updated as much as possible, so if you have anything to add or correct feel free to contact me or leave a comment.

Update 2018-04-08:

  • Added reference to plc4x
  • Added link to the second part

Update 2017-03-14:

  • I have added a git repo with various thematic network captures of S7 communication click here
  • I am no longer working with Siemens equipment however due to the interest in the topic I have started writing part 2 of this article. Since I have no access to real devices it is going to be based on the different traffic captures I have laying around and my memories. Expect more gaps to fill
  • I have limited experience dealing with userdata messages (other than SZL reads and cyclic updates they are mostly used for development, programming and debugging purposes) so I am not sure if I can cover them in a meaningful way based on the few pcaps I have

0ctf 2018 - Black Hole Theory

Writeup for the 2018 0ctf pwn challenge Black Hole Theory Continue reading

Google CTF - Inst Prof Writeup

Published on June 25, 2017

Google CTF - Wiki Writeup

Published on June 24, 2017