Finally, as the last part of the blog series we will have a look at the network traffic observed. We will do this in two sections, the first one will cover a few things useful to know if we are in the situation that Wireshark can dissect the traffic for us. The second section will look into the situation where the dissection is not nicely done by Wireshark.
We start by looking into a normal connection setup on Port 102 TCP. Frames number 2 to 4 shown in figure 1 representing the standard three way handshake to establish the TCP connection. If this is done successfully, the COTP (Connection-Oriented Transport Protocol) session is established by sending a connection request (frame 5) and a confirmation of the connection (frame 6). Based on this the S7 communication is setup, as shown in frame 7 and 8.
Zooming into frame number 5, we can see the how Wireshark dissects the traffic and provide us with the information that we are dealing with a connect request.
In order to use Wireshark or tshark to filter for these frames we can apply the following display filters:
Looking into the S7 frames, in this case frame number 7, we can see the communication setup function code sent to the PLC.
Apart from the function code for the communication setup (“0xf0”), we can also learn something very important here. The field “Protocol Id” contains the value “0x32”, this is the identifier of the S7 protocol and according to our experience, this protocol id has significant impact if Wireshark can dissect the traffic, like shown above, or not.
With the example of requesting the download of a block (containing logic or variables etc.) we will have a look on how jobs are send to the PLC. By the way, the communication setup is already a job sent to the PLC. To keep the screenshot as clean as possible, the traffic is filtered to only show traffic identified as S7 protocol.
The IP-address ending with .40 is the PLC and the IP-address ending with .10 is the source of the commands and data. Indicated by the blue background, frames number 43 to 57 represent the download of a block to the PLC. Frames 43 and 44 are initializing the download of the block, in this case a block called “DB1”. We can see that the .10 host is sending a “Job” to the PLC (.40) in frame 43, the PLC acknowledge this job in the next frame (number 44) and starts to download the block in frame 46. So, in essence the PLC is instructed to actively request (download) the block. The block is not pushed to the PLC. This also explains why the term “download to the PLC” is used when a project is transferred form an engineering workstation to a PLC. The download of the block ends with frames 55 and 56, where the corresponding function code is transmitted and acknowledged.
A few handy display filters for Wireshark or tshark:
In regards of the download of blocks (s7comm.param.func == 0x1b), the actual data is contained in the acknowledge frames send (s7comm.header.rosctr == 3).
Working with nicely dissected traffic in Wireshark or tshark is always a bless. But sometimes we do not have this luxury. The communication between a workstation running TIA Portal version 15.1 and a Siemens Simatic S7-1200 PLC is shown in figure 5.
A filter was applied to only show the traffic between the workstation and the PLC, you must believe us here that we did not hide the S7 protocol. We can see similarities between this traffic and the traffic discussed earlier: it involves Port 102/TCP and COTP. We might not have the luxury of nicely dissected traffic, but we are not out of luck.
We can use Wireshark’s “Follow TCP Stream” function and the search functionality to look out for some very specific strings. If you are searching for a specific string in a traffic dump, it would be pretty cumbersome to manually follow every TCP stream and use the search field in the resulting window. Thankfully Wireshark offers something better. While you are in the main windows of Wireshark hit “CTRL+f” which will add the search functionality below the display filter area.
Above you also can see the choices we have to make in order to search for strings. Key is that we are looking into “Packet bytes” and we are looking into finding a “String”. An example where we searched for the string “ReleaseMngmtRoot” is shown below:
You may ask yourself why all this is important. An excellent question we are going to answer now.
Based on our observations we can identify the following actions by analysing the occurrences of specific strings:
We will start with the download of changes of a block to the PLC. Below you can see which string occurrences are to be expected and in which direction they are send.
The TCP stream view in figure 9 shows the second, third and fourth step. Please be aware that the String “PLCProgramChange” in the schema above refers to the last occurrence which is followed by the next string “DLTransaction”. Traffic in blue is traffic from the PLC to the Workstation and traffic marked with red background is the other direction
The strings in the “ReleaseMngmtRoot” sections containing some very valuable information as demonstrated in the following screenshot.
In the blue section the PLC is transmitting its state to the Workstation and the Workstation does the same in the red section. We can actually see the name of the project deployed on the PLC, in this case: “BridgeControl” followed by information on the PLC. For example, “6ES7212-1AE40-0XB0” is the article number of the PLC, which can be used to find more information on it. If you follow along, you can see that the workstation wants to deploy changes taken from a project file called “BridgeControl_Malicious”.
Finding the name of the changed block is possible, but it really helps if you know the names of the possible blocks, as it will be hidden in a lot of characters forming (nonsense) strings. The block changed in our case was “MotorControl”.
Figure 12 shows the schema for changes to text lists/libraries, following the same convention as above.
Be aware though that “TextLibrary…” is followed by its content, so expect a lot of strings to follow.
Downloading the complete software means that everything is downloaded to the PLC, instead of just the changes.
Please note that the string “PLCProgram” also appears in what we assume is the banner or functions list. But is has been observed at the position shown above only in case of a full software download to the PLC. Of cause “TextLibrary…” is followed by the content of the library, like mentioned previously.
The hardware configuration can be downloaded to the PLC together with the software changes or as a single task. In both cases the following schema was observed
Please note that the string “HWConfiguration” also has been observed as part of a TextLibrary.
Above excerpt shows the two “ReleaseMngmtRoot” occurrences as well as the occurrence of the “HWConfiguration” string. Again, blue indicating traffic from the PLC to the workstation, red the other direction.
Now if you have followed the post until this section, it is the time to mention that there is at least one dissector available for this version of the protocol. The protocol discussed in the second section is usually referred to as S7commPlus. You can identify it by looking at the location where you would expect the value “0x32” (dissected as field “Protocol Id”), in case of S7commPlus it contains “0x72”.
The screenshot above was taken from Wireshark with a freely available S7CommPlus dissector installed. Although we are not going to cover the dissector in this blog post, we mentioned it for completeness.
If you like to play around with it, you can find it online at least on https://sourceforge.net/projects/s7commwireshark/ . One word of caution: Use at your own risk. We did not spend much time using this dissector yet. The dissector downloaded from sourceforge comes as a precompiled dll file that needs to be placed in corresponding folder (In our testing: “C:\Program Files\Wireshark\plugins\3.6\epan” as we used Wireshark Version 3.6). Do your own risk assessment when dealing with files like dlls downloaded from the internet.
Even if we cannot start our analysis on well dissected traffic, we still can identify specific patterns in the traffic. Of cause this all applies to traffic that is not encrypted, enabling us to have a look into the bits and bytes transferred.
This post marks the end of this series of blog posts. We again like to stress the point that the discussed content is based on testing and observations. There is no guarantee that our testing has been including all possibilities, or for example that different versions of the TIA portal do behave the same way. More research and testing is needed, to learn more on behaviour of software evolved in OT. If we would like to have reached one goal with this series of posts, it would be to have inspired at least one person to perform research in this area and share it with the community.
Olaf Schwarz is a Senior Incident Response Consultant at NVISO. You can find Olaf on Twitter and LinkedIn.
You can follow NVISO Labs on Twitter to stay up to date on all out future research and publications.