Normal view

There are new articles available, click to refresh the page.
Before yesterdayNVISO Labs

Investigating an engineering workstation – Part 4

6 July 2022 at 08:00

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.

Nicely dissected traffic

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.

Figure 1: Connection setup shown in Wireshark

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.

Figure 2: Details of frame number 5

In order to use Wireshark or tshark to filter for these frames we can apply the following display filters:

  • cotp.type == 0x0e # filter for connection requests
  • cotp.type == 0x0d # filter for connection confirmation

Looking into the S7 frames, in this case frame number 7, we can see the communication setup function code sent to the PLC.

Figure 3: Communication setup function code

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.

Figure 4: Download a block to a PLC

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:

  • s7comm.header.rosctr == 1 # filter for jobs being requested to be performed
  • s7comm.header.rosctr == 3 # acknowledge of requested jobs
  • s7comm.param.func == 0x1a # downloads being requested/acknowledged
  • s7comm.param.func == 0x1b # download of blocks
  • s7comm.param.func == 0x05 # write a variable
  • s7comm.param.func == 0x04 # read a variable
  • s7comm.param.func == 0xf0 # communication setup, also shown above

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).

Less nicely dissected traffic

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.

Figure 5: Traffic between workstation running TIA 15.1 and S7-1200 PLC in Wireshark

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.

Figure 6: Search file in main windows of Wireshark

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:

Figure 7: Example of searching “ReleaseMngmtRoot” in frames

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:

  • Download of changes of a block
  • Download of changes to a text list (Text library)
  • Download of the complete software, not only the changes
  • Download of the hardware configuration
Download changes of a block

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.

Figure 8: String occurrences for download of changes of a block

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

Figure 9: Excerpt of TCP stream view showing steps 2,3 and 4

The strings in the “ReleaseMngmtRoot” sections containing some very valuable information as demonstrated in the following screenshot.

Figure 10: TCP Stream View on “ReleaseMngmtRoot” sections

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 11: Presence of block name in TCP Stream view
Downloading changes for text lists

Figure 12 shows the schema for changes to text lists/libraries, following the same convention as above.

Figure 12: String occurrences for download of changes of a text lists/libraries

Be aware though that “TextLibrary…” is followed by its content, so expect a lot of strings to follow.

Figure 13: TCP stream view showing parts of a downloaded text library
Downloading complete software

Downloading the complete software means that everything is downloaded to the PLC, instead of just the changes.

Figure 14: String occurrences for a complete software download

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.

Downloading hardware configuration

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

Figure 15: String occurrences for a hardware configuration download

Please note that the string “HWConfiguration” also has been observed as part of a TextLibrary.

Figure 16: TCP Steam view of a hardware configuration download

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”.

Figure 17: S7commPlus Protocol ID

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 . 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.

Conclusion & Outlook

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.

About the Author

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.

Investigating an engineering workstation – Part 3

20 April 2022 at 08:00

In our third blog post (part one and two are referenced above) we will focus on information we can get from the projects itself.

You may remember from Part 1 that a project created with the TIA Portal is not a single file. So far we talked about files with the “.apXX” extension, like “.ap15_1” in our example. Actually these files are used to open projects in the TIA Portal but they do not contain all the information that makes up a project. If you open an “.ap15_1” file there is not much to see as demonstrated below:

Figure 1: .at15_1 file content excerpt

The file we are actually looking for is named “PEData.plf” and located in the “System” folder stored within the “root” folder of the project. The “root” folder is also the location of the “.ap15_1” file.

Figure 2: Showing content of project “root” and “System” folder

As demonstrated below, the “PEData.plf” file is a binary file format and reviewing its content does not show any usefully information at first sight.

Figure 3: Hexdump of a PEData.plf file

But we can get useful information from the file if we know what to look for. When we compare the two “PEData” files of projects, where just some slight changes were performed, we can get a first idea how the file is structured. In the following example two variables were added to a data block, the project was saved, downloaded to the PLC and the TIA Portal was closed saving all changes to the project. (If you are confused with the wording “downloaded to the PLC”, do not worry about it too much for now. This is just the wording for getting the logic deployed on the PLC.)

The tool colordiff can provide a nice side-by-side view, with the differences highlighted, by using the following command. (The files were renamed for a better understanding):

colordiff -y <(xxd Original_state_PEData.plf) <(xxd CHANGES_MADE_PEData.plf)

Figure 4: colordiff output showing appended changes

The output shows that the changes made are appended to the “PEData.plf” file. Figure 4 shows the starting offset of the change, in our case at offset 0xA1395. We have performed multiple tests by applying small changes. In all cases, data was appended to the “PEData.plf” file. No data was overwritten or changed in earlier sections of the file.

To further investigate the changes, we extract the changes to a file:

dd skip=660373 if=CHANGES_MADE_PEData.plf of=changes.bin bs=1

We set the block size of the dd command to 1 and skip the first 660373 blocks (0xA1395 in hex). As demonstrated below, the resulting file, named “changes.bin”, has the size of 16794 bytes. Exactly the difference in size between the two files we compared.

Figure 5: Showing file sizes of compared files and the extracted changes

Trying to reverse engineer which bytes of the appended data might be header data and which is actual content, is way above the scope of this series of blog posts. But with the changes extracted and the use of tools like strings, we still get an insight on the activities.

Figure 6: Parts of strings output when run against “changes.bin” file

Looking through the whole output, we can immediately find out that the change ends with the string: “##CLOSE##”. This is also the only appearance of this specific string in the extracted changes. Further we can see that not far above the “##CLOSE##” string there is the string “$$COMMIT$”. In this case we will find two occurrences for this specific string, we will explain later why this might be the case.

Figure 7: String occurrences of “##CLOSE” and “$$COMMIT$” at the end of changes

The next string of interest is “PLUSBLOCK”, if you review figure 6, you will already notice it in the 8th line. In the current example we get three occurrences of this string. No worries if you are already lost in which string occurred how many times etc., we will provide an overview shortly. Before showing the overview, it will help to review more content of the strings output.

Below you can review the changes we introduced in “CHANGES_MADE_PEData.plf” compared to the project state represented by “Original_state_PEData.plf”.

Figure 8: Overview of changes made to the project

In essence, we added two variables to “Data_block_1”. These are the variables “DB_1_var3” and “DB_1_var4”. These variable names are also present in the extracted changes as shown in figure 9. Please note, this block occurs two times in our extracted changes, and also contains the already existing variable names “DB_1_var1” and “DB_1_var2”.

Figure 9: Block in “changes.bin” containing variables names

One section we need to mention before we can start drawing conclusions from the overview is the “DownloadLog” section, showing up just once in our changes. We will have a look at the content of this section and which behaviour we observed later in this blog post.

Overview and behaviour

As promised earlier, we finally start showing an overview.

Line number String / Section of interest
22 Section containing the variable names
35 $$COMMIT$
58 Section containing the variable names
78 Start of “DownloadLog”
101 $$COMMIT$
109 ##CLOSE#
Table 1: Overview of string occurrences in “changes.bin”

The following steps were performed while introducing the change:

  1. Copy existing project to new location & open the project from the new location using the TIA Portal
  2. Adding variables “DB_1_var3” and “DB_1_var4” to the already existing datablock “Data_block_1”
  3. Saving the project
  4. Downloading the project to the PLC
  5. Closing the TIA Portal and save all changes

The “$$COMMIT$” string in line 35 and 101 seems to be aligning with our actions in step 3 (saving the project) and step 4 & 5 (downloading the project & close and save). Following this theory, if we would skip step 3, we should not get two occurrences of the variable name section and would not see the string “$$COMMIT$” twice. In a second series of tests we did exactly this, resulting in the following overview (of course the line numbers differ, as a different project was used in testing).

Line number String / Section of interest
28 Section containing the variable names
40 Start of “DownloadLog”
70 $$COMMIT$
75 ##CLOSE#
Table 2: Overview of string occurrences in “changes.bin” for test run 2

This pretty much looks like what we expected, we only see one “$$COMMIT$”, one section with the variable names and one less “PLUSBLOCK”. To further validate the theory, we did another test by creating a new, empty project and downloaded it to the PLC (State 1). Afterwards we performed the following steps to reach State 2:

  1. Adding a new data block containing two variables
  2. Saving the project
  3. Adding two more variables to the data block (4 in total now)
  4. Saving the project
  5. Downloading the project to the PLC
  6. Closing the TIA Portal and save all changes

If we again just focus on the additions made to the “PEData.plf” we will get the following overview. Entries with “####” are comments we added to reference the steps mentioned above.

Line number String / Section of interest
32 Start of “DownloadLog”
194 Section containing the variable names (first two variables)
223 $$COMMIT$
#### Comment: above added by step 2 (saving the project)
266 Section containing the variable names (all four variables)
270 $$COMMIT$
#### Comment: above added by step 4 (saving the project)
278 Section containing the variable names (all four variables)
456 Start of “DownloadLog”
509 $$COMMIT$
513 ##CLOSE#
#### Comment: added by step 5 and 6
Table 3: Overview of string occurrences in test run 3

The occurrence of the “DownloadLog” at line 32 might come as a surprise to you at this point in time. As already stated earlier, the explanation of the “DownloadLog” will follow later. For now just accept that it is there.

Conclusions so far

Based on the observations described above, we can draw the following conclusions:

  1. Adding a change to a project and saving it will cause the following structure: “PLUSBLOCK”,…changes…, “$$COMMIT$”
  2. Adding a change to a project, saving it and closing the TIA Portal will cause the following structure: “PLUSBLOCK”,…changes…, “$$COMMIT$”,”##CLOSE#”
  3. Downloading changes to a PLC and choosing save when closing the TIA Portal causes the following structure: “PLUSBLOCK”,…changes…, “PLUSBLOCK”,DownloadLog, “$$COMMIT$”,”##CLOSE”

The “DownloadLog” is a xml like structure, present in clear in the PEData.plf file. Figure 10 shows an example of a “DownloadLog”.

Figure 10: DownloadLog structure example

As you might have guessed already, the “DownloadTimeStamp” represents the date and time the changes were downloaded to the PLC. Date and time are written as Epoch Unix timestamp, and can be easily converted with tools like CyberChef using the appropriate recipe. If we take the last value ( “1641820395551408400” ) from the “DownloadLog” example and convert it, we can learn that there was a download to the PLC happening on Mon 10 January 2022 13:13:15.551 UTC. By definition Epoch Unix timestamps are in UTC, we can confirm that the times in our tests were created based on UTC and not on the local system time. Also demonstrated above, the “DownloadLog” can contain past timestamps, showing a kind of history in regards of download activities. Remember what was mentioned above, the changes to a project are appended to the file, this also is true for the “DownloadLog”. So an existing “DownloadLog” is not updated, instead a new one is appended and extended with a new “DownloadSet” node. Unfortunately, it is not as straight forward as it may sound at the moment.

Starting again with a fresh project, configuring the hardware (setting the IP-Address for the PLC), saving the project, downloading the project to the PLC and closing the TIA Portal (Save all changes) we ended up with one “DownloadLog” containing one “DownloadTimeStamp” in the PEData.plf file:

  1. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″

As next step we added a data block, again saving the project, downloading it to the PLC and closing the TIA Portal saving all changes. This resulted in the following overview of “DownloadLog” entries:

  1. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
  2. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
  3. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
    • DownloadTimeStamp=”1639754268869841200″

The first “DownloadLog” is repeated, and a third “DownloadLog” is added containing the date and time of the most recent download activity. So overall, two “DownloadLogs” were added.

In the third step we added variables to the data block followed by saving, downloading and closing TIA Portal with save.

  1. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
  2. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
  3. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
    • DownloadTimeStamp=”1639754268869841200″
  4. DownloadLog
    • DownloadTimeStamp=”1639754084193097100″
    • DownloadTimeStamp=”1639754268869841200″
    • DownloadTimeStamp=”1639754601898276800″

This time only one “DownloadLog” was added, which repeats the content of “DownloadLog” number 3 and also contains the most recent date and time. We repeated the same actions of step 3 again, observing the same behaviour. One “DownloadLog” is added, which repeats the content of the previous “DownloadLog” and adds date and time of the current download activity. After doing this, we did not observed anymore “DownloadLog” entries added to the “PEdata.plf” file, no matter which changes we introduced and downloaded to the PLC. In further testing we encountered different behaviours of the “DownloadLog” and if it is repeated as a whole or not (Occurrence 2 in the examples above). Currently we believe that only 4 “DownloadLog” entries, showing new download activity, are added to the “PEData.plf” file. If a “DownloadLog” entry is just repeated, it is not counted.

Conclusion on the DownloadLog
  1. When “DownloadTimeStamp” entries are present in a “PEData.plf” file, they do represent download activity.
  2. If there are 4 unique “DownloadLog” entries in a “PEData.plf” file, we cannot tell (from the “PEData.plf” file) if there was any download activity after the most recent timestamp in the last occurrence of a unique “DownloadLog” entry.

Overall Conclusions & Outlook

We have shown that changes made to a project can be isolated and to a certain part analysed with tools like strings, xdd or diff. Further we have demonstrated that we can reconstruct download activity from a project, at least up to the first four download actions. Last but not least we can conclude that more testing and research has to be performed to get a better understanding of data points that can be extracted from projects. For example, we did not perform research to see if we can identify strings representing the project name or the author name for the project in the “PEData.plf” file without knowing them upfront. Further we only looked at the Siemens TIA Portal Version 15.1, different versions might produce other formats or behave in a different way. Further Siemens is not the only vendor that plays a relevant role in this area.

In the next part we will have a look at network traffic observed in out testing. Stay tuned!

About the Author

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.

Investigating an engineering workstation – Part 2

30 March 2022 at 08:00

In this second post we will focus on specific evidence written by the TIA Portal. As you might remember, in the first part we covered standard Windows-based artefacts regarding execution of the TIA Portal and usage of projects.

The TIA Portal maintains a file called “Settings.xml” under the following path: C:\Users\$USERNAME\AppData\Roaming\Siemens\Portal V15_1\Settings\. Please remember we used version 15.1 only. The path contains the version number for the TIA Portal, so at least the path will most likely change for different versions. It is also possible that the content and the behaviour of the nodes discussed below changes with different versions of the TIA Portal.

The file can be investigated with a text editor of your choice as it has a plain XML structure. Many nodes contain readable strings, although there are some exceptions that contain encoded binary data.  

A few nodes are of specific interest:

  • “LastOpenedProject”
  • “LRUProjectStorageLocation”
  • “LRUProjectArchiveStorageLocation”
  • “LastProjects”
  • “ConnectionServices”
  • “LoadServices”

We will look at each of these nodes, what information they contain and how they behaved in our testing. As the file is present for a specific user, everything in it is related to that specific user account. So if we state that some information represents the last opened project, it is meant for the specific user the Settings.xml file belongs to and not globally for the entire system.


Figure 1: Settings.xml LastOpenedProject node

This node is located under the SettingNode named “General” and contains one child node. As you can see from the screenshot above, this child node is a full path to an “.ap15_1” file. As the name already implies, this is the last project opened with the TIA Portal.  In this example the project root folder is “testproject_09”, the storage location of the project is located at “C:\Users\nviso\Documents\Automation\” and the file used to open the project “testproject_09.ap15_1”.


Last opened project

  • If the TIA Portal is opened and closed without opening a project, the child note will be empty. This also represents exactly what happened: no project was opened.
  • The value is not affected if a project is removed from the recently used projects in the TIA Portal. Removing a project from this list is a native build in function of the TIA Portal.
Figure 2: TIA Portal dialog to open and remove recently used projects


Figure 3: Settings.xml LRUProjectStorageLocation node

This node is located under the SettingNode named “General”, as a neighbour of the “LastOpenenProject” node we discussed earlier. It also contains only one child node representing the path to the location where the most recently opened project is located. More precisely to the location of the root folder of the project.


Path to folder containing the most recently opened project

  • The value of the child node is not affected if the TIA Portal is opened & closed without opening any project.
  • The value is not affected if a project is removed from the recently used projects in the TIA Portal.


Figure 4: Settings.xml LRUProjectArchiveStorageLocation node

This node is located under the SettingNode named “General”, as a neighbour of the “LastOpenenProject” node we discussed earlier. If a project file is opened in the TIA Portal and the archive function is used (Main menu bar: Project -> Archive…) the full path to the folder specified in the “Target path” field is written to this value.

Figure 5: TIA Portal Archive Project Dialog

Full path to the most recent folder specified to archive a project.

  • The value is overwritten if a different location is chosen while archiving a project.
  • Unless the archive function is used, the node is not present in the “Settings.xml” file.


Figure 6: Settings.xml LastProjects node

The “LastProjects” node is a child node of the SettingsNode named “ProjectSettings”. The “ProjectSettings” node is located at the same level as the “General” node discussed earlier. As shown in the excerpt above, the node contains a list of full path entries for “.apXX” files. This list shows the opened projects represented in chronological order, with the most recent project on top.


Chronological orders list of opened projects

  • The content of this node is not affected when the TIA Portal is opened and closed without opening a project.
  • If a project is removed from the list of recently used projects, the corresponding “String” node containing the full path to the project is removed from the list. The chronological order will still be intact afterwards.
  • Entries in this list are unique. If a project already present in the list is opened again, the entry will be moved to the top position.
  • In our testing we have seen 10+ child nodes for opened projects. We did not test for a maximum value of projects that are tracked in the “LastProjects” node.
  • If a new project is created and saved in the TIA Portal, it will show up in this list, but not show up in the Jump List. (We covered this in part 1 of the series)


Figure 7: Settings.xml ConnectionService node (parts have been remove for readability)

The “ConnectionService” node is a neighbour of the “ProjectSettings” and the “General” node. It contains child nodes named after the full path of projects. These child nodes can contain the creation date and time of the project in UTC, stored in a child node called “CreationTime”. Further they can contain a child node called “ControllerConfiguration” which might have several child nodes for configured PLCs. Theses PLC nodes (“{1052700-1391}” in the example above) shows information how to communicate with the PLC, in the node named “OamAddress”. As demonstrated in the screenshot the “OamAddress” node can give us information like the IP-Address and subnet-mask used to reach the PLC.


List of projects that were worked on within the TIA Portal. Under certain circumstances creation time of the project in UTC and connection information for configured PLCs is shown.

  • The content of this node and its child’s is not affected when the TIA Portal is opened and closed without opening a project.
  • The content of this node and its child’s is not affected if a project is removed from the recently used projects in the TIA Portal.
  • A “SettingNode” entry for a specific project is not added directly after an empty project is created, neither is it added when an empty project is re-open again.
  • A “SettingNode” including the project creation timestamp in UTC is created when you start to configure the project, for example by adding a PLC to it.
  • The creation timestamp is taken from within the project, so if a project file is copied to a different host and opened there, the creation date and time of the original project is listed.
  • The “SettingNode” for a specific project is extended with a “SettingNode” named “ControllerConfiguration” if communication with a configured PLC has been performed, in example using the “go online” function or downloading logic to the PLC.
  • If multiple PLCs are configured, the “ControllerConfiguration” node contains multiple child nodes representing the configuration for each of the PLCs.
  • Our testing has shown that the child nodes containing the information per PLC are not randomly named. If the same PLC is used in multiple projects, the node will get the same name. Applying this to our example above means, that if the PLC is added to three different projects, you will find a SettingNode named “{1052700-1391}” in all three “ControllerConfiguration” sections. Of cause only if the conditions to write a “ControllerConfiguration” are met.
  • If a PLC is removed from a project, the corresponding child node under “ControllerConfiguration” is not removed.


Figure 8: Settings.xml LoadServices node

The “LoadService” node is a neighbour of the “ProjectSettings” and the “General” node. It contains child nodes named after the full path of projects. As shown above, the child nodes given an ID as name, like we already saw within the “ConnectionServices” section.


List of projects that were worked on within the TIA Portal.

  • The content of this node and its child’s is not affected when the TIA Portal is opened and closed without opening a project.
  • The content of this node and its child’s is not affected if a project is removed from the recently used projects in the TIA Portal.
  • A project will only show up under “LoadServices” if a PLC is added to the project and configuration is done to communicate with the PLC, like setting an IP-Address to its interface.
  • According to our testing, the child nodes of a project node under “LoadServices” are not randomly named and behave the same way as mentioned in the “ConnectionServices” section. The screenshot above shows the same PLC added to two different projects. The name does not match with the named assigned for a PLC in the “ConnectionServices” node section.
  • If a PLC is removed from a project, the corresponding child node under “LoadService” is not removed.
  • If a complete project, with PLCs configured is copied to a different location on the same machine, opened and an interaction to the PLC is initiated with the “go online” function, no additional entry in the “LoadService” section for the copied project is created. If the IP-Address configuration for the PLC is changed in the project, an entry will be created though.  At the moment it is unclear why this happens. A theory could be that the configuration of the IP-Address creates the entry and the first interaction with the PLC just updates the entry if it exists. If it does not find a matching entry nothing is done.


Manually searching in .xml files and highlighting the important notes is a cumbersome process. In order to provide some help for extracting the interesting parts of a “Settings.xml” file I took the liberty and created a small python tool. You can download the tool from my GitHub repository.

By invoking it with the command below, the discussed nodes are extracted:

python3 ./ -f PATH_TO_SETTINGS.XML

Figure 9: Sample output of

At the end of this second blog post some general notes on the “Settings.xml” file. This file belongs to the user, no additional privileges would be needed to change or delete the file. If you delete the file and start the TIA Portal, it will automatically create a fresh “Settings.xml” file. So it seems pretty easy to manipulate or clean this file. Still the user (or the adversary) first needs to be aware that this file exists and which information it stores! The file is written as part of the tasks performed when the TIA Portal is closed normally. If the TIA portal crashes, or the process get killed by other means, the file will not be updated.

Conclusion & Outlook

In this second part we have shown that the “Settings.xml” does store valuable information and should be considered when analysing machines running the TIA portal. Further we have introduced a free tool to extract this data and as a small bonus a KAPE target to collect the “Settings.xml” file.

In the third part of this series of blog posts, we will have a look at what data we can extract from projects created with the TIA Portal.

About the Author

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.

Investigating an engineering workstation – Part 1

15 March 2022 at 09:00

In this series of blog posts we will deal with the investigation of an engineering workstation running Windows 10 with the Siemens TIA Portal Version 15.1 installed. In this first part we will cover some selected classic Windows-based evidence sources, and how they behave with regards to the execution of the TIA Portal and interaction with it. The second part will focus on specific evidence left behind by the TIA Portal itself and how to interpret it. Extracting information from a project and what needs to be considered to draw the right conclusions from this data will be the focus of the third post. Last but not least we will look at the network traffic generated by the TIA portal and what we can do in case the traffic is not being dissected nicely by Wireshark.

For the scope of this series of blog posts we look at the Siemens TIA (Totally Integrated Automation) Portal as the software you can use to interact with, and program PLCs. This is a simplified view, but it is sufficient to follow along with the blog posts. A PLC, or Programmable Logic Controller, can be viewed as a specially designed device to control industrial processes, like manufacturing, energy production and distribution, water supply and much more.  The Siemens Siematic S7-1200, we will mention later in this series, is just one example of the many representatives of this family.

If you approach your first engagement looking at a Windows system running the TIA Portal, you might have the same thought as I had: “Will some of the useful evidences, which I know and used in  other Windows-based investigations, be there waiting to be unearthed?” Since it is always better to know such things before an actual incident takes place, we will cover some of the more standard evidences and how they behave in regards of the TIA Portal. Please note, we will not elaborate on the back and forth of every Windows-based evidence we mention, as this is not meant to be a blog post explaining standard evidence.

Evidence of Execution is available as you would expect. If you know what to look for, it perhaps helps in forming answers faster and more precise.

The Prefetch artifact, if enabled on the system, would be written for “SIEMENS.AUTOMATION.PORTAL.EXE” and can be parsed like any other prefetch file. Additionally, the prefetch file for “SIEMENS.AUTOMATION.DIAGNOSTIC” also gets written or updated when the TIA Portal is started. If we have a look at the ShimCache (aka AppCompatCache) we can try to find the last time of execution by investigating the SYSTEM registry hive. In case of newer Windows systems, like in our example a Windows 10 system, you are out of luck in regards of the last time of execution. It is no longer recorded.

Investigating a Windows 10 system and having the System registry hive already open, the BAM key (ControlSet00x\Services\bam\State\UserSettings\$SID) will provide us with information on date and time for application execution. Knowing the executable name (“Siements.Automation.Portal.exe”) and using it in a simple search quickly reveals the information we are looking for.

Reviewing more user related evidence, by analyzing the NTUser.dat for the user accounts in scope of the investigation, leads us to the UserAssist key. Reviewing the subkeys starting with: “CEBFF5CD…” and “F4E57C4B…” will give us the expected information, like run count, last executed time and so on. Just make sure you are looking into the correct values for each subkey. In the subkey starting with “F4E57C4B…” it is shortcuts we are looking into. In our installation the .lnk files are named “TIA Portal V15.1.lnk”, which is the default value, as it was not renamed by us.

Figure 1: TIA Portal related content in UserAssist Subkey “F4E57C4B…”

For the second subkey (“CEBFF5D…”) we are looking at the executables, so the actual executable name is what we should search for.

Figure 2: TIA Portal related content in UserAssist Subkey “CEBFF5D…”

But what about finding projects that have been present or opened on the machine you are investigating?

First of all we should have an idea how a project looks like. Usually it is not a single file, instead it is a structure of multiple folders and subfolders. Furthermore it contains a file in the root directory of the project folder which you are using to open the project in the TIA Portal. The file extension of these files changes with the Version of the TIA Portal: “.apVERSION” is the current schema. This would mean, a file created with the TIA Portal Version 15.1 will have “ap15_1” as file extension, if created with TIA Portal Version 13 it will be “ap13” as file extension.  

The following screenshot shows the file extensions which can be opened with the TIA Portal Version 15.1 and provides further examples of the naming schema.

Figure 3: TIA Portal Version 15.1 supported file extensions

Below you can see an overview of the files and the directory structure of a test project, in our case created with Version 15.1 of the TIA Portal:

Figure 4: Example listing of a test project created with TIA Portal V15.1

Equipped with this information we can check if and how the “.ap15_1” extension show up in classic file use and knowledge artefacts.

Reviewing the recent files for a user, by investigating the RecentDocs key in the corresponding NTUSER.dat hive shows a subkey for the “.ap15_1” extension.

Figure 5: RecentDocs subkey for .ap15_1 file extension
Figure 6: Example content of RecentDocs subkey for .ap15_1 file extension

The second screenshot shows an excerpt of the “.ap15_1” key parsed by Registry Explorer. Please note, that if a project file is opened via the “Recently used” projects listing, shown on the starting view of the TIA Portal, the RecentDocs key is not updated.

Figure 7: TIA Portal view to open recently used projects

While we are dealing with user specific evidence, we can also check if Jump Lists are available as we would expect. We can use the tool JLECmd by Erik Zimmermann to parse all Jump Lists and review the results in Timeline Explorer. By applying a filter to only show files ending with “.ap” we get the overview shown below.

Figure 8: Jump Lists entries showing .ap15_1 files

Here you can clearly see that we can parse out entries related to “.ap15_1” files for “Quick Access” and also for an App Id not known to JLECmd. This App Id is related to the TIA Portal and we can now also identify the automatic destinations file to open or parse the specific file if we want or need. It will be “4c28c7c161e44256.automaticDestinations-ms”, in our case stored under “C:\Users\nviso\AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations”.  If a project is created and saved in the TIA Portal it will not show up in the Jump List. Further if you choose to open a project from the “Recently used” projects list, like described above, the Jump List of the TIA Portal will not be changed.

Figure 9: TIA Portal Recently used projects vs. Jump List

In figure 9 we demonstrated the potential differences between the Jump List (1.) and the “Recently used” projects in the TIA Portal (2.). Obviously the two most recent projects listed by the TIA Portal are missing in the Jump List. The “testproject12.ap15_1” file relates to an already existing project opened via the TIA Portal functionality and the “Pro_dev_C64_blast” project was created via the TIA Portal. The content of the Jump List is shown via the Windows Start menu in this example. Reviewing the Jump List with JLECmd validates these results.

The OpenSaveMRU, also user account specific evidence, is another a place where we can look for the “.ap*” file extension and review activity. Opening the NTUSER.dat for the user account in focus and following the path down to the “OpenSavePidlMRU” key already shows the subkey for a file extension of interest. As always you need to be aware of the evidence you are looking at, the OpenSaveMRU is maintained by the Windows shell dialog box, projects will be showing up here based on if they are opened or saved via the dialog box or not. Double-clicking a “.ap15_1” file will not make it show up here, luckily for us we have the Jump List and the “RecentDocs” key mentioned above.  Also note, that opening a project via the “Recently used” projects lists of the TIA Portal, mentioned above in the section discussing “RecentDocs”, will not change the OpenSaveMRU.

Figure 10: OpenSaveMRU key containing subkeys for ap15_1 files

Needless to say that you can also search the $MFT for files with the extension of interest.

A few things need to be mentioned in regards of managing expectations:

  • The evidence produced by the Windows Operating System or the TIA Portal is not there for forensic or incident response investigations. It usually servers a different purpose than we are using it for. That being said, it should be understood that evidence might behave completely different after software updates or in older/newer versions of the software.
  • Further it is not guaranteed that the software will produce the same evidence in any imaginable edge case.
  • The blog posts are based on our observations and testing results.

Conclusion & Outlook

The standard evidences on a Windows System can already bring some good insights into activities around the TIA Portal. However, we must be aware that the TIA Portal offers its own functions for opening and creating projects, which do not update the jump list, for example. For these cases we can review the “Settings.xml” file. We will focus on the “Settings.xml” file and information we can get out of raw project files in the upcoming blog posts.

About the Author

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.

Amcache contains SHA-1 Hash – It Depends!

7 March 2022 at 09:00

If you read about the Amcache registry hive and what information it contains, you will find a lot of references that it contains the SHA-1 hash of the file in the corresponding registry entry. Now that especially comes in handy if files are deleted from disk. You can use the SHA-1 extracted from the Amcache to search indicator of compromise lists or simply on the internet in general.

I recently came across a discussion, where someone was asking about an explanation of SHA-1 hashes recorded in Amcache not matching the SHA-1 hash of the actual files. Another person claimed that this can happen, as the SHA-1 hash in Amcache is only calculated for the first 31,457,280 bytes (about 31.4 MB) of large files. Well time to take this to a test.

The Amcache registry hive is typically used in investigations to gain knowledge on executed files. It can be found at the following path: C:\Windows\AppCompat\Programs\Amcache.hve

The executables of 7-Zip and RegistryExplorer were chosen to be candidates for testing. Let’s start by calculating their SHA-1 hashes on disk:

Figure 1: Calculating SHA-1 hashes for files on disk

As you can see, the files have the following SHA-1 hash values:

File name SHA-1 hash
7z.exe 1189CEBEB8FFED7316F98B895FF949A726F4026F
RegistryExplorer.exe E50B8FA6F73F76490818B19614EE8AEFD0AA7A49
Table 1: SHA-1 hashes on disk

If we now execute both files and afterwards acquire the Amcache hive, we can have a look at the recorded values. In this test KAPE was used to acquire the Amcache and Registry Explorer to open it.

Figure 2: Amcache.hve: Root\InventoryApplicationFile\7z.exe|afe683e0fa522625

By reviewing the FileId value and removing the prefix ‘0000’, we can see that this actually is the SHA-1 hash value of the file on disk. But the size of the 7z.exe file is below 31,457,280 bytes.

Figure 3: Amcache.hve: Root\InventoryApplicationFile\registryexplorer|54c8640d4bd6cc38

Doing the same exercise again for RegistryExplorer.exe leads to an expected SHA-1 hash value of: 0f487a4beec16dba123cbc860638223abb51d432 . That value clearly does not match the SHA-1 hash we calculated earlier. The RegistryExplorer.exe file has a file size larger than 31,457,280 bytes.

So if it is true, that the SHA-1 stored in Amcache is calculated at max on the first 31,457,280 bytes of a file, we should be able to get the same result as above.

Figure 4: Getting SHA-1 hash of first 31,457,280 bytes

Above you can see how the dd command was used to get a file containing only the bytes that should be considered for the hash calculation of the Amcache entry. The hashes for both the original file and the stripped file are shown as well.

Putting this all next to each other:

File SHA-1 hash value
Original on disk E50B8FA6F73F76490818B19614EE8AEFD0AA7A49
Amcache entry 0f487a4beec16dba123cbc860638223abb51d432
Stripped file on disk 0f487a4beec16dba123cbc860638223abb51d432
Table 2: Comparing SHA-1 hashes for RegistryExplorer.exe

The SHA-1 hash of the first 31,457,280 bytes matches what is recorded in Amcache. I tested this on Windows 10 and Windows 8, both 64 bit versions, showing exactly the same behaviour.


The testing performed shows that the Amcache records a SHA-1 hash for files, but for larger files only for the first 31,457,280 bytes. This also means that taking the SHA-1 hash from Amcache and search it online has its limitations. The size of the file needs to be taken into account.

Two very basic sayings in digital forensics and incident response have been proven right:

It depends!

Always validate!

About the Author

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.