In this walkthrough, we’ll go over the TryHackMe room created by Dainok Attacking ICS Plant #1. This room will go over the absolute basics of attacking a plant that uses Modbus. We’ll also get a brief intro into some of the operational technology that can be found.
Task 1
This first task is to read through the information provided. If you’ve never heard of any of this before it’s worth looking into. Operational technology (OT) can be found everywhere from CT scanners in hospitals to what makes an FPSO work. Check out my last post: OT Cyber Security Risk Consultant from BSc Ethical Hacking.
Task 2
For our first task, we’ll need to understand what the code is doing here. To do this task you’ll need to have a basic understanding of how to write Python code. Firstly, download the files that are provided as part of the room, unzip them and let’s look at the “discovery.py” file.
For question one, we’re looking for the function that is used to read the holding registers pymodbus library. Fortunately, the code is very easy to read as the function is just named “read_holding_registers”.
For question 2 we’re being asked about the functions again. This time, “Which is the function used to write holding registers?”. To find the answer look through the other code snippets you have. Specifically, “attack_move_fill.py” where you’ll find that the function is called “write_register”.
Task 3
In task 3 we get our first look at an ICS plant. This is the simulation of a bottle-filling plant. What’s on your screen isn’t a video, rather it’s a full-on simulation which you’ll be able to interact with.
This simulation was created by Jan Seidl and they’ve kindly made the code open which can be found here. If you’re somewhat proficient with python I’d recommend that you take a look at the source code. Unfortunately, the repository is no longer maintained and won’t just run on your machine out of the box but we can still interact with the one on TryHackMe.
The next question we have to answer requires that we use one of the scripts named “discovery.py”. This script is rather old and to get it to work you’ll have to remove the “.sync” from the line that imports “pymodbus.client”. I made a small change to the code because I’m extremely lazy that would print out the number of registers.
With the script running in a loop we can observe that there is 16 registers.
The values we get are either “1” or “0” meaning that they are binary. Watching the script run and observing the values you can see that the last one does not change. To find the answers to the next few questions it’s a simple matter of taking your time to observe the plant and what is going on. There are a few helpful hints on TryHackMe if you’re stuck.
How many phases can we observe?
3How many sensors can we observe?
2How many actuators can we observe?
3Using the script discovery.py, how many registers can we count?
16After the plant is started and a bottle is loaded, how many registers are continuously changing their values?
4Which is the minimum observed value?
0Which is the maximum observed value?
1Which registry is holding its value?
16Which registries are set to 1 while the nozzle is filling a bottle?
2 4Which registries are set to 1 while the roller is moving the bottles?
1 3Which is the color of the water level sensor?
redWhich is the color of the bottle sensor?
greenIf you observe the plant at the very beginning, which is the registry associated with the roller?
3Based on the previous answer, which is the registry associated with the water level sensor?
1Task 4
For this last task, we’re going to play around with the plant to discover what register is the one that is associated with the nozzle. Follow the plant for a while and see which registers change.
The question tells us that it is either 2 or 4. We’re going to use the “set_registry.py” script to change the state of one of the registers and observe what happens. To do this start by removing the “.sync” like before. Next, restart the simulation then immediately run the command:
python3 set_registry.py <Machine IP> 2 1
This will set registry 2 to a value of “1” (True), this stops the plant’s track. From that we can guess that the nozzle register is 4, however, it’s worth checking. Alter the previous command by changing “2 1” to “4 1” and go watch the simulation. Now we’ve confirmed that register 4 is the nozzle enter that as the answer.
Task 5
Task 5 is a chance for you to play around with the plant using the scripts provided. For this section. I hope you run into problems because I did and it taught me a lot. There are a dozen or so programs on GitHub (mbusd, Golang version, even a GUI tool) that you can use to interact with the plant and learn a little bit about the protocol and ICS. Don’t bother with the questions on the page. Instead, just play about with it.
Conclusion
This box was a very very basic look at ICS. It was fun though, I quite liked being able to interact with something that could be physical. In IT your actions rarely affect the physical world; the only thing I can think of is mining malware speeding up fans. With this room, you will have gotten a feel for interacting with the world with computers. In the rest of pen-testing timing rarely matters. Whereas in ICS if you turn on the nozzle you’d do more damage when the line is stopped and less when it’s moving. Take a moment to think about how this production line flows and imagine for a moment it’s not water into bottles but molten metal into crucibles. Now think of the impact, it has happened before. ICS is definitely its own world. Thinking more about IT hacking interacting with the physical world; if you can think of anything please leave a comment.