The cyber security Capture The Flag (CTF) competitions in the Information Technology (IT) field are held frequently around the world, but CTFs focused on Operational Technology (OT) remain relatively rare and less accessible. Unlike traditional IT CTFs that emphasize web applications or network vulnerabilities, OT CTF challenges revolve around systems such as PLC, SCADA, RTU, and Industrial Control Systems (ICS). These scenarios require participants to possess specialized ICS knowledge in identifying vulnerabilities, exploiting misconfigurations, and defending critical infrastructure commonly found in power grids, manufacturing environments, transportation and water treatment facilities. OT CTFs offer a unique opportunity to bridge the gap between IT and OT security, combining cybersecurity skills with deep understanding of industrial protocols like Modbus, DNP3, S7Comm, and IEC 61850.
The Critical Infrastructure Security Showdown (CISS) is one of the few international events that provides a dedicated OT CTF platform for participants annually, which held at the Singapore University of Technology and Design (SUTD) and organized by the iTrust research center. CISS provides the great opportunity brings together global CTF experts to tackle realistic OT cybersecurity challenges. For more details, please visit the CISS 2024 website.
In this article, I’ll introduce one of the IT-OT hybrid challenges I designed for last year’s CISS ( the challenge is one of the top three favorites in CISS 2024) and walk through the steps to solve it. If you're interested in participating the OT CTF competition, don’t miss the upcoming CISS 2025: https://itrust.sutd.edu.sg/ciss-2025/.
# Author: Yuancheng Liu
# Created: 2024/06/02
# version: v_0.1.3
Challenge Introduction: Palantir Control
Each year, the CISS CTF features a creative storyline to inspire challenge design. The 2024 edition adopted the theme "The Orthanc Obstacles", based on The Lord of the Rings: The Two Towers. ( As shown in the CISS2024 poster and medal below )
Figure-00 CISS2024 poster and medal screenshot
In this context, the challenge I designed—Palantir Control—draws from the iconic scene where Saruman uses the Palantír to control the Orthanc Tower as shown below in the movie:
Figure-01 The Lord of the Ring Saruman
This challenge simulates a mini OT ICS environment (SCADA layer network) to illustrate how an IT-based cyberattack can compromise and crash an OT system. It features a Programmable Logic Controller (PLC) and a remote control interface (such as HMI) that mimics a simplified SCADA system. Participants are tasked with using IT penetration techniques to infiltrate the network, escalate privileges, and ultimately manipulate the OT system to retrieve the flag.
In Palantir Control challenge, participants will progress through multiple stages of attack:
-
IT Penetration – Network Scanning
-
IT Penetration – UDP Port Probing
-
IT Exploitation – HTTP Web Server CGI Vulnerability
-
IT Attack – Web Admin Password Brute-force
-
OT Attack - PLC misconfiguration exploiting
-
OT Attack – PLC False Data Injection
The challenge not only emphasizes technical skills across IT and OT domains but also reflects real-world risks where IT-layer compromises can lead to OT failures. Prepare to breach Orthanc and uncover the secrets hidden within its cyber walls. The challenge is designed based on one of my PLC Honey Pot project: https://www.linkedin.com/pulse/python-plc-honeypot-project-yuancheng-liu-vks8c
Challenge Background Story and Question
CTF Challenge Background Story
In the shadow of Isengard, Saruman the white has harnessed the dark power of the Palantír, a mystical black crystal ball, to remotely control the Fiery Eye perched atop the Orthanc Tower. With each command he sends, the Eye shifts and burns, guiding his relentless Orc army toward domination.
But hope remains. Armed with Gandalf's secret intelligence, Sam and Frodo set out on a dangerous mission to sabotage Saruman’s wicked control system. The key to his power lies in a concealed Operational Technology (OT) network:
-
A Programmable Logic Controller (PLC) within the Orthanc Tower manipulates the Eye based on incoming remote commands.
-
A remote controller, operated by Saruman through the Palantír, sends those commands using a specialized OT protocol.
-
The Eye's state changes via PLC holding registers, and Saruman monitors feedback through the Palantír’s response data.
To stop the spread of darkness, the hobbits must act swiftly as shown below:
Figure-02 Challenge background story overview
-
Sam must infiltrate the tower, breach the control system, and manipulate the logic behind the Fiery Eye.
-
Frodo, risking everything, must approach Saruman’s domain and uncover a hidden backdoor to extract data directly from the black crystal.
Only by disrupting this critical control chain can they save Middle-earth from ruin.
CTF Challenge Question
Challenge 1 – Sam’s Mission [IT Challenge]
Objective: Help Sam infiltrate the Orthanc Tower and uncover the inner workings of the control system.
Task:
-
Scan the network to identify the Orthanc Tower Controller (PLC).
-
Locate the device’s web-based management interface.
-
Bypass authentication to access internal configuration data.
Flag Location: Hidden within the PLC web interface, possibly encoded or embedded in a diagnostics or config page.
Challenge 2 – Frodo’s Mission [OT Challenge]
Objective: Assist Frodo in disrupting the communication between Saruman and the Orthanc Tower.
Task:
-
Discover the remote OT controller that Saruman uses via the Palantír.
-
Interact with it to retrieve operational data.
-
Execute a false data injection or similar disruption to manipulate the Fiery Eye’s behavior.
Flag Location: Embedded in the controller’s feedback data, accessible after disrupting its normal operation.
🖧 Network Configuration
The network configuration part will NOT provide to the participants, they need to use network scanning tool to figure out the network topology and each teams' configuration may be different.
This challenge environment is composed of three Virtual Machines (VMs)—two for the IT-OT simulation and one for participant access. All VMs are placed within the same subnet to allow direct communication. The topology is shown below:
Figure-03 Challenge environment network topology
IP Address Configuration:
-
PLC Controller (Remote Control Program) IP:
172.23.155.208
-
PLC Device IP:
172.23.155.209
-
Participant VM IP:
172.23.144.1
In this challenge, participants interact with a simulated IT-OT environment that emulates a simplified SCADA system. The setup includes:
-
A PLC device controlled via Modbus-TCP
-
A remote controller VM acting as Saruman’s Palantír interface
-
An Transaction VM (Ubuntu 20.04), which has been previously compromised
Key Scenario Details
-
The remote controller regularly sends Modbus-TCP instructions to the PLC, triggering actions based on PLC ladder logic (e.g., coil activation).
-
The IT-support engineer VM is accessible to participants with full
sudo
privileges but lacks direct access to monitor or control the PLC. -
However, the remote controller exposes an open UDP port, which participants can interact with to query the current operational status of the PLC (e.g., output coil states).
-
Participants must write a customized UDP client to pull the real-time status data from the controller.
-
Using IT-penetration and OT-manipulation techniques, participants will attempt to corrupt or alter the PLC’s expected behavior, such that the controller receives unexpected or erroneous responses.
The ultimate goal is to cause a logic failure or inconsistency that makes the remote controller generate a state error code, which contains the flag.
Challenge Design
Participants will use the transaction VM to install tools or develop custom attack scripts necessary for interacting with and exploiting the IT-OT environment. While a high-level system workflow governs the interaction sequence, it is not disclosed to participants during the CTF is shown below:
Figure-04 Challenge environment system workflow diagram
The core of the challenge centers on a PLC simulator, which executes a hidden ladder logic routine. The PLC simulator VM exposes two key services to the network:
-
Modbus-TCP Service: Port
TCP:502
-
Web Interface (HTTP): Port
TCP:5000
Every 2 seconds, the test environment simulates an OT operation cycle:
-
The remote controller VM randomly loads a predefined PLC holding register configuration and the corresponding expected coils output states from its internal database.
-
It sends a Modbus-TCP write request to update the holding registers in the PLC simulator.
-
The PLC simulator updates its internal register values, executes its ladder logic, and updates its coil output states accordingly.
-
The remote controller then queries the PLC's coils to verify whether the response matches the expected result.
-
Based on this match, the remote controller determines whether the PLC test passes or fails.
✅ Normal Operation (Test Pass):
If the PLC responds with correct coil states, the system is considered to be functioning properly. When participants send a UDP packet containing getstate
to the remote controller at port UDP:3000
, they will receive a response such as:
state:normal;;;...
❌ Fault Condition (Test Failed):
If the PLC’s response does not match the expected coil output, the remote controller flags an error. In this case, when the participant sends getstate
to UDP:3000
, they will receive:
state:error;{error-code-xxxxxxxxxxxxxxxx}
The {error-code}
is the CTF flag.
If the communication challenge disconnected, the controller will response message "PLC rejected connection
".
If the participants didn't send the correct string "getstate", the controller will response "Error: Input request invalid
" .
🎯 Challenge Objective
CTF participants must create an attack that causes the PLC’s output state to deviate from the expected result, thereby triggering an error condition in the remote controller.
Example Scenario:
-
The controller sets the PLC’s 8 holding registers to:
[0, 1, 1, 0, 1, 0, 0, 1]
-
The ladder logic should produce output coils 1 - 4 as:
[1, 0, 0, 1]
-
If the remote controller reads:
[1, 0, 1, 1]
for those coils instead, it flags the error and returns the flag via UDP. But the participant need to read fast as after 1 second the controller will reset and start another new round execution.
Participants must discover how to disrupt the logic chain—whether through misconfiguration, race condition, unauthorized input, or injection—so that the PLC responds with an incorrect coil state. We leave two sec for the participants to do the false data injection attack and about one sec to let them to read the flag, the clock time interval is shown below:
Figure-05 Inject time stamp and the clock time interval diagram
Steps to Solve the Challenge
Now lets go through the detailed steps to solve the challenge. The participant needs to solved the IT challenge 1st then can start do the OT challenge part.
Solve Sam’s Mission [IT Challenge]
Step 1: Discover the PLC Web and Modbus-TCP Services
Begin by identifying live hosts on the subnet using fping
or any nmap host scan sweep method. Once identified, scan the suspected PLC IP to enumerate its open ports:
nmap -sS -Pn -T5 -p- 172.23.155.209
A typical scan reveals open Modbus-TCP (port 502) and HTTP Web Interface (port 5000) on the PLC VM as shown below:
Figure-06 Nmap port scan result
Since the transaction VM is Ubuntu-server version (without desktop), you’ll need to port-forward the web interface to your local machine:
ssh -L 127.0.0.1:5000:172.23.155.209:5000 -J @ @172.23.144.1
Now, open the URL http://127.0.0.1:5000
on local browser to navigate to the PLC's web interface. The participants can through the story and challenge introduction page as show below :
Figure-07 Challenge PLC VM web interface home page
Step 2: Investigate the Web UI and Find Hidden Hint-1
After read the challenge detail from the web, click the “Login” button in the top navigation bar to view the login form:
Figure-08 Challenge PLC VM web interface authorization page
Now you need to brute force break the password, but before that you need to figure out what's the user name. The Orc's message in the picture highlight Saruman, if you try saruman
(or other general account such as admin
) with some password such as "1234567
", the site returns a login reject message: Login account does not exist
.
Figure-09 Challenge PLC VM web interface login fail screen shot
There must be some clue about the account, Look the login page again, there's a suspicious drop-down button labeled "Gandalf's Message" at the bottom. When the drop down box expanded, we can get some message as shown below:
Figure-10 Challenge PLC VM web interface login page Gandalf's Message
Look at the string, it seems Gandalf doesn't provide any useful message, but wait, the "line" under his message seems suspicious! May be Gandalf's message is corrupted, let's check the web source:
Figure-11 Challenge PLC VM web interface login page html source
This “line” is actually a 5-pixel high image named hint01
. Inspect the page source to reveal the image:
Figure-12 Challenge PLC VM web interface login page reveal Gandalf's Message
Yes! Now Gandalf appeared and gives us a URL to open the door:
http://tower_ip:5000/userlogin/xxxx/xxxx
If the participants try the URL in their browser, it will show whether the credential is correct as shown below:
http://172.23.155.209:5000/userlogin/Saruman/xxxx
This returns a login error: User name or password incorrect!
(as shown below)
Figure-13 Challenge PLC VM login API test
This confirms the endpoint works and supports URL-based credential injection, but the URL is still not useful ! As it is same as the login page, any thing I missed ? Let's check the new web source:
Figure-14 Challenge PLC VM login CGI response source
There is one not visitable paragraph:
<p hidden>Sarumanscrow said:</p>
Sarumanscrow said:
Could Sarumanscrow
be the valid username? Try logging in with that:
Figure-15 Find the correct login user name
The login reject error changed to User password incorrect!
. We can confirm there is one user account which is "Sarumanscrow" can be used to login the PLC website.
Step 3: Brute Force the Password and Retrieve the Flag
With the username discovered (Sarumanscrow
), and the credential injection endpoint confirmed, you can now perform a dictionary-based brute force attack using Python:
import time
import urllib
import urllib.request
ipAddr = "172.23.155.209"
passwordDictFile = "solveCTFScripts\\10-million-password-list-top-1000000.txt"
passwordList = []
with open(passwordDictFile, 'r') as fh:
passwordList = fh.readlines()
for password in passwordList:
password = password.strip()
url = "http://%s:5000/userlogin/Sarumanscrow/%s" %(ipAddr, password)
response = urllib.request.urlopen(url)
message = str(response.read())
print(message)
if 'User name or password incorrect!' in message:
time.sleep(0.1)
continue
else:
print("Find password: %s" %str(password))
break
In the actual CTF, the password is randomly selected from the dictionary. In this test run, for example, it was admin
as shown below:
Figure-15 Brute force attack to get the password
Once you successfully authenticate, the PLC web interface will change to login state and PLC web interface will present a congratulatory message in blue color:
“Congratulations, you have solved the IT challenge. Search the flag from the pages.”
The left nav-bar under the introduction will show Fiery Eye Control and Orthanc Tower Control as shown below:
Figure-17 Challenge PLC VM web interface login successful
When the participants switch to the Fiery Eye Control (PLC ladder logic page) , then will find the IT challenge flag:
Figure-18 Find the IT challenge flag in the Fiery Eye Control page
We can get the IT challenge flag CISS2024_SAM_FLAG (in real competition, this will be a randomly generated flag string )
- Now the IT challenge is solved !
Solve Frodo’s Mission [OT Challenge]
Step 1: Discover the Controller’s UDP Service
Based on the ladder logic webpage Hints02
in the PLC Ladder logic page (as shown below), the participants need to find the opened UDP service port on the PLC controller node (172.23.155.208) to get the current PLC operation verification state.
Figure-19 Get the hint02 from the PLC web
To do this, create a simple Python script to scan the UDP ports on the controller VM as shown below:
import time
from socket import *
host = "172.23.155.208"
s = socket(AF_INET, SOCK_DGRAM)
for port in range(10,65532):
try:
print("Try port %s" %str(port))
data = b"Test Message"
s.sendto(data,(host,port))
s.settimeout(1)
print ((s.recvfrom(1024)))
print("Find opened port: %s" %str(port))
break
except:
pass
Run the UDP port scan program and get result:
Try port 2991
Try port 2992
Try port 2993
Try port 2994
Try port 2995
Try port 2996
Try port 2997
Try port 2998
Try port 2999
Try port 3000
(b'Error: input request invalid: Test Message', ('172.23.155.208', 3000))
Find opened port: 3000
UDP Port 3000 is confirmed to be open.
Step 2: Build UDP Client Connect to PLC Controller
With the UDP service port discovered, use the Hint03 in the ladder logic page (as shown below) to send the getstate
string to the controller VM and retrieve the PLC state:
Figure-20 Get the hint03 from the PLC web
You can use the attack script https://github.com/LiuYuancheng/PLC_and_RTU_Simulator/blob/main/Modbus_PLC_Simulator/src/udpCom.py as an example to keep sending the UDP message:
Figure-21 Get the normal response from PLC controller VM
Running the client will return the current status of coils C0 to C3. If the PLC coils result verification passed, the controller will identify PLC is operating normally, you’ll see the "normal" world in the response message.
Step 3: Build a False Data Injection (FDI) Attack Script
The OT challenge requires participants to over write the PLC holding registers to induce a malfunction. Based on the OT- challenge flag hint: the participants need to mess up the PLC operation to make the remote controller detect PLC working error, then read the error code. Now the participants switch to the PLC ladder logic page to learn about the ladder logic, here are 8 PLC holding registers are used in the ladder logic [HR0 - HR7] (As shown below) :
Figure-22 Analyze the PLC ladder logic diagram
If the participants can inject false data in some of the registers, the out put may be changed. For example, if change the state HR6, HR0 or HR7 may changed the coil's output as they are in the "AND" gate logic. (If change single state of a register in a "OR" gate logic such as HR1, HR4 may not make influence of the output, the equivalent circuit diagram is shown below )
Figure-23 Analyze the circuit diagram
The participants can use https://github.com/LiuYuancheng/PLC_and_RTU_Simulator/blob/main/Modbus_PLC_Simulator/src/modbusTcpCom.py as an example create the simple PLC FDI attack script program to over write the holding registers' value.
However if they only run the scrip directly, the attack fail message will show up (the register value change request is rejected):
Figure-24 PLC false data injection failed
The problem is the attack VM's IP 172.23.144.1
is not in the PLC register "allow read" and "allow write" IP addresses list. So all the false data injection request are rejected by the PLC.
Click the "Orthanc Tower Control" at the slider bar, it will change to "PLC Configuration" as shown below, the participants need to add the attack VM's IP in the allow write IP address (As shown below):
Figure-25 Challenge PLC VM web configuration page
Fill in the attack VM's IP address in the text field and press the green "Add" button, then the attacker's IP will be added in the allow write PLC's addresses list as shown below:
Figure-26 Add the allow write IP address to PLC configuration
Now the participants can run the attack program again and they can see that the set result return true, the FDI attack program is changing the PLC's holding register's value now:
Figure-27 PLC false data injection accepted
Now the false data injection attack program is ready to use.
Step 4: Trigger Controller Error and Retrieve the OT Flag
To complete the challenge:
-
Also add the transaction VM’s IP to the Allow Read IP List so we can get the holding register state
-
Modify your script to:
-
Read the current values of
HR0–HR7
-
Invert each bit (1 → 0, 0 → 1)
-
Write the reversed values back to the PLC
-
This will distort the coil outputs, and the controller logic will detect the abnormal state. As the inject time also need to be accuracy , so the attacker need to keep running the FDI program and the controller state reading program at the same time. After a while, they will see the error code as shown below:
We can get the OT challenge flag PLC_EXECUTE_ERROR_FLG (in real competition, this will be a randomly generated flag string )
- Now the OT challenge is solved !
You’ve successfully disrupted the Palantir Control logic using a False Data Injection Attack and retrieved the operational error flag.
Remark:
There are two questions from the participants about whether they can use other solution to "by pass" the challenge:
Q1: Can I use False command injection to modified the coils output directly ?
Ans: The PLC Configuration didn't provide the PLC Coil "allow read" and "allow write" setup API, user are not able to modify the PLC's coil directly.
Q2: Can I use ARP spoofing and MITM attack to modify the controller's Modbus request or Modbus response message directly ?
Ans: During the competition, we allow the participants to download some ARP spoofing / mitm tool such as ettercap, but refer to the network topology in the network configuration section, the middle switch we have configured static ARP entries on the switch, so most of the ARP spoofing/mitm tool will not work.
Conclusion
The Palantir Control challenge demonstrates how IT vulnerabilities can cascade into OT system failures, exposing critical infrastructure risks. By combining web exploitation, protocol manipulation, and false data injection, participants bridge IT/OT security domains—a crucial skill for defending industrial environments. If you are interest about the Critical Infrastructure CTF Competition, don't miss this the CISS2025 on 1st Sep: https://itrust.sutd.edu.sg/ciss-2025/
Thanks for spending time to check the article detail, if you have any question and suggestion or find any program bug, please feel free to message me. Many thanks if you can give some comments and share any of the improvement advice so we can make our work better ~
Last edit by LiuYuancheng([email protected]) at 06/06/2025, if you have any problem, please send me a message.