Investigating an engineering workstation – Part 3

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
22Section containing the variable names
58Section containing the variable names
78Start of “DownloadLog”
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 numberString / Section of interest
28Section containing the variable names
40Start of “DownloadLog”
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 numberString / Section of interest
32Start of “DownloadLog”
194Section containing the variable names (first two variables)
####Comment: above added by step 2 (saving the project)
266Section containing the variable names (all four variables)
####Comment: above added by step 4 (saving the project)
278Section containing the variable names (all four variables)
456Start of “DownloadLog”
####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.

Series Navigation<< Investigating an engineering workstation – Part 2

One thought on “Investigating an engineering workstation – Part 3

Leave a Reply