FIRST SecLounge CTF 2020 – ICS Challenges

The FIRST CTF 2020 included an ICS track that consisted of 3 questions related to the investigation of different industrial scenarios.


Tripping over DNP3 

What is the packet number of the first command that causes a breaker to be tripped? 


To solve this challenge, we have to understand the DNP3 protocol. To find the right packet the most interesting fields are the Function Code and the Trip Control Code. The SELECT and OPERATE function codes are used to issue a control request, which will only be activated after the OPERATE request was received and no error is detected. The Trip Control Code can have four values, from which “2″ means Trip. 

In Wireshark filter for “dnp3.ctl.trip == 2” and select the first packet with Operate function code. 


Flag: 352 


Weird Modbus Traffic 

We have captured what appears to be Modbus traffic, but it doesn’t seem to have any normal Modbus function codes or data. Within this weird traffic, can you determine the Network ID of the network that stops all of the nodes? 



The first step was to find the right protocol description: CiA 309-2 Interfacing CANopen with TCP/IP Part 2: Modbus/TCP mapping. 

The commands can be found in the sub-index field, where 0x11 means STOP_ALL_NODES:

Below is a short description of the Modbus data:


Flag: D6 


PLC Firmware Injection 

A malicious firmware stub was uploaded to an ICS device via serial communication. The captured serial communication is found in capture.logicdata. Your goal is to decode the serial traffic, extract the firmware stub binary, and reverse engineer the firmware stub. If the integer 120 was passed as an argument to the function in the firmware stub, what would the function return? 


After some googling, we found that Salea Logic software can be used to examine logicdata files. We downloaded the software and opened the file. The first task was to map the channels correctly.  

According to Wikipedia, the SPI bus specifies four logic signals: 

  • SCLK: Serial Clock (output from master) 
  • MOSI: Master Output Slave Input, or Master Out Slave In (data output from master) 
  • MISO: Master Input Slave Output, or Master In Slave Out (data output from slave) 
  • SS: Slave Select (often active low, output from master) 

We used the SPI Analyzer feature of the Salea Logic software with the following settings:

With the right settings, we could extract the data:

We got a file with the following content: 

This file is a Motorola S-Record:

The first line of the file is the header. The header tells us which architecture to use when we analyze the file.  

We loaded the file to Ghidra with the following settings:

By simply looking at the decompiler view, we got the function that we needed.  

 The solution, if the integer 120 is passed to the function: (120 * 120) / 300 << 1 = 96. 



Albert Zsigovits