Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .devcontainer/virtual/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ services:
context: ../..
dockerfile: software/landing/Dockerfile
restart: always
network_mode: host
ports:
- "80:80"
networks:
virt-cybics:
ipv4_address: 172.18.0.20
cap_add:
- NET_ADMIN
- NET_RAW
Expand Down
26 changes: 26 additions & 0 deletions software/landing/ctf_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,32 @@
"training_content": "training/defense_ids/README.md"
}
]
},
"reverse_engineering": {
"name": "🔍 Reverse Engineering",
"description": "Recover credentials from compiled ICS maintenance utilities",
"challenges": [
{
"id": "plc_auth",
"title": "PLC Maintenance Auth Tool",
"description": "Reverse engineer a vendor maintenance binary to recover the operator password",
"points": 150,
"tag": "re",
"flag": "CybICS(x0r_1s_n0t_encrypti0n_4_PLC)",
"hint": "The password is XOR-encoded with a single constant key. Check byte arrays in the binary.",
"training_content": "training/reverse_engineering/challenge1/README.md"
},
{
"id": "hmi_validator",
"title": "HMI Safety Override Tool",
"description": "Derive a valid 16-char authorization code from the validation algorithm",
"points": 200,
"tag": "re",
"flag": "CybICS(HMI_byp4ss_PLC_s4f3ty_1nt3rl0ck)",
"hint": "Each byte is XORed with a rolling 4-byte key then offset by its index. Invert both operations.",
"training_content": "training/reverse_engineering/challenge2/README.md"
}
]
}
}
}
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions software/landing/templates/ctf.html
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
.tag-evasion { background: rgba(245,158,11,0.15); color: #fbbf24; }
.tag-defense { background: rgba(34,197,94,0.15); color: #4ade80; }
.tag-hardware { background: rgba(236,72,153,0.15); color: #f472b6; }
.tag-re { background: rgba(20,184,166,0.15); color: #2dd4bf; }

</style>
</head>
Expand Down
116 changes: 116 additions & 0 deletions training/reverse_engineering/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# 🔓 Reverse Engineering — CTF Challenges

> **MITRE ATT&CK for ICS:** `Credential Access` `Collection` | [T0812 - Default Credentials](https://attack.mitre.org/techniques/T0812/) | [T0893 - Theft of Operational Information](https://attack.mitre.org/techniques/T0893/) | [T0110 - Brute Force — Password Cracking](https://attack.mitre.org/techniques/T0110/)

## 📋 Overview

Vendors and system integrators often embed credentials or authorization logic directly in compiled
binaries — sometimes with minimal obfuscation — leaving them exposed to anyone with access to the
firmware or filesystem.

Two maintenance utilities were recovered from CybICS field devices during an incident response
exercise. Both binaries are compiled for Linux/x86-64. Your task is to reverse engineer each one,
recover the embedded credentials or authorization code, and retrieve the hidden diagnostic flag.

These challenges model a realistic ICS threat scenario: hardcoded secrets in maintenance tools
are a persistent problem in OT environments, where firmware updates are rare and security audits
even rarer.

---

## 🎯 Challenges

### Challenge 1 — PLC Maintenance Auth Tool (`plc_auth`) · 150 pts · Easy

A maintenance binary found on the OpenPLC runtime filesystem.
It prompts for an operator password before revealing a diagnostic code.

**Goal:** Find the password → get the flag.

→ See [challenge1/README.md](challenge1/README.md)

---

### Challenge 2 — HMI Safety Override Tool (`hmi_validator`) · 200 pts · Medium

A safety-interlock override utility recovered from the HMI workstation.
It validates a 16-character authorization code using a keyed transformation.

**Goal:** Derive a valid authorization code → get the flag.

→ See [challenge2/README.md](challenge2/README.md)

---

## 🛠️ Getting the Binaries

Download the challenge binaries from the CTF server:

```bash
# Challenge 1
wget http://localhost/static/challenges/plc_auth/plc_auth
chmod +x plc_auth

# Challenge 2
wget http://localhost/static/challenges/hmi_validator/hmi_validator
chmod +x hmi_validator
```

---

## 🧰 Recommended Tools

| Tool | Purpose |
|-------------|-----------------------------------|
| `strings` | Quick plaintext extraction |
| `ltrace` | Trace library calls (strcmp etc.) |
| `strace` | Trace syscalls |
| `gdb` | Dynamic analysis / breakpoints |
| `ghidra` | Full decompilation (recommended) |
| `radare2` | Disassembly + scripting |
| `objdump` | Quick disassembly |
| `python3` | Solve encoding math offline |

---

## 🛡️ Security Framework References

<details>
<summary>Click to expand</summary>

### MITRE ATT&CK for ICS

| Tactic | Technique | ID | Description |
|--------|-----------|-----|-------------|
| Initial Access | Default Credentials | [T0812](https://attack.mitre.org/techniques/T0812/) | Credentials embedded in vendor maintenance tools |
| Collection | Theft of Operational Information | [T0893](https://attack.mitre.org/techniques/T0893/) | Extracting configuration and diagnostic data from ICS binaries |
| Credential Access | Brute Force — Password Cracking | [T0110](https://attack.mitre.org/techniques/T0110/) | Recovering passwords through analysis or offline cracking |

**Why this matters:** Hardcoded credentials in ICS maintenance tools are a well-documented supply-chain risk. An attacker with physical or network access to a field device can extract these tools and recover credentials that grant privileged access to the wider control system — bypassing all authentication controls on the management interface.

### MITRE D3FEND — Defensive Countermeasures

| Technique | ID | Description |
|-----------|-----|-------------|
| Software Binary Analysis | [D3-SBA](https://d3fend.mitre.org/technique/d3f:SoftwareBinaryAnalysis/) | Analyzing binaries to detect embedded secrets before deployment |
| Credential Hardening | [D3-CH](https://d3fend.mitre.org/technique/d3f:CredentialHardening/) | Eliminating hardcoded credentials from software and firmware |
| Authentication Event Monitoring | [D3-AEM](https://d3fend.mitre.org/technique/d3f:AuthenticationEventMonitoring/) | Monitoring for use of shared or vendor maintenance credentials |

### NIST SP 800-82r3 Reference

| Control Family | Controls | Relevance |
|----------------|----------|-----------|
| **Identification and Authentication (IA)** | IA-5 | Authenticator management — prohibiting hardcoded credentials |
| **Supply Chain Risk Management (SR)** | SR-6, SR-11 | Supplier assessment and component authenticity verification |
| **Configuration Management (CM)** | CM-7 | Least functionality — restricting maintenance tool deployment |

**Why NIST 800-82r3 matters here:** NIST 800-82r3 Section 6.2.3 explicitly calls out hardcoded credentials as a critical risk in OT environments. IA-5 (Authenticator Management) requires that credentials not be embedded in software, while SR-6 (Supplier Assessments) recommends auditing vendor-supplied tools for exactly this type of vulnerability before deployment. These challenges demonstrate why binary analysis of vendor tools should be part of every ICS security assessment.

</details>

---

## 🔍 Solutions

Full solution writeups are in `challengeN/solution/writeup.md`.
**Do not open these before attempting the challenge yourself.**
19 changes: 19 additions & 0 deletions training/reverse_engineering/challenge1/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CC := gcc
CFLAGS := -O0 -g0 -Wall -Wextra -static
TARGET := plc_auth
SRC := src/plc_auth.c
DOCKER_DEST := ../../../software/landing/static/challenges/$(TARGET)/$(TARGET)

.PHONY: all clean deploy

all: $(TARGET)

$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $@ $<

# Copy built binary into the Docker challenge folder
deploy: $(TARGET)
cp $(TARGET) $(DOCKER_DEST)

clean:
rm -f $(TARGET)
127 changes: 127 additions & 0 deletions training/reverse_engineering/challenge1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# 🔓 PLC Maintenance Auth Tool

> **MITRE ATT&CK for ICS:** `Credential Access` | [T0812 - Default Credentials](https://attack.mitre.org/techniques/T0812/) | [T0110 - Brute Force — Password Cracking](https://attack.mitre.org/techniques/T0110/)

## 📋 Overview

During incident response on the CybICS gas pressure control system, forensic analysts
discovered a custom maintenance utility on the OpenPLC runtime filesystem. The binary is believed
to have been left by the original equipment vendor to allow privileged operator access
without going through the standard OpenPLC web interface.

The binary prompts for an operator password and — if correct — prints a vendor diagnostic
code containing a flag hidden in the system configuration.

```
==========================================================
CybICS PLC Maintenance Tool v1.2.0
Gas Pressure Control System - Operator Access
(c) CybICS Industrial Systems
==========================================================
System: HPT/GST Pressure Controller
Protocol: Modbus TCP
Status: CONNECTED
----------------------------------------------------------

Enter operator password: _
```

This models a realistic supply-chain risk: vendors frequently embed hardcoded credentials in
maintenance tools shipped with field devices, often with only superficial obfuscation, leaving
them recoverable by anyone with access to the binary.

## 🎯 Task

Reverse engineer `plc_auth` to recover the operator password and obtain the flag printed
after successful authentication.

The flag has the format `CybICS(flag)`.

1. Download the binary from the CTF server and make it executable
2. Run it to understand what it does
3. Perform static analysis to recover the password — start with `strings`, then examine the comparison logic in a disassembler if needed
4. Use dynamic analysis to observe the comparison at runtime without knowing the password in advance
5. Enter the recovered password to obtain the flag

```bash
wget http://localhost/static/challenges/plc_auth/plc_auth
chmod +x plc_auth
./plc_auth

# Static recon
file plc_auth
strings plc_auth

# Dynamic analysis
ltrace ./plc_auth
```

## 🛡️ Security Framework References

<details>
<summary>Click to expand</summary>

### MITRE ATT&CK for ICS

| Tactic | Technique | ID | Description |
|--------|-----------|-----|-------------|
| Initial Access | Default Credentials | [T0812](https://attack.mitre.org/techniques/T0812/) | Vendor-supplied maintenance tools with embedded operator passwords |
| Credential Access | Brute Force — Password Cracking | [T0110](https://attack.mitre.org/techniques/T0110/) | Recovering the password by analyzing the binary offline |

**Why this matters:** Hardcoded credentials in ICS maintenance binaries are a persistent supply-chain threat. An attacker with even read-only access to a field device can extract vendor tools, reverse engineer the password, and gain privileged access to the control system — entirely bypassing the authentication controls visible to operators. The 2021 Oldsmar water treatment incident highlighted how single-factor, vendor-supplied credentials can become the weakest link in an OT environment.

### MITRE D3FEND — Defensive Countermeasures

| Technique | ID | Description |
|-----------|-----|-------------|
| Software Binary Analysis | [D3-SBA](https://d3fend.mitre.org/technique/d3f:SoftwareBinaryAnalysis/) | Auditing vendor binaries for hardcoded secrets before deployment |
| Credential Hardening | [D3-CH](https://d3fend.mitre.org/technique/d3f:CredentialHardening/) | Requiring vendors to eliminate hardcoded credentials from firmware |
| Authentication Event Monitoring | [D3-AEM](https://d3fend.mitre.org/technique/d3f:AuthenticationEventMonitoring/) | Alerting on the use of shared maintenance credentials |

### NIST SP 800-82r3 Reference

| Control Family | Controls | Relevance |
|----------------|----------|-----------|
| **Identification and Authentication (IA)** | IA-5 | Authenticator management — prohibiting embedded plaintext or weakly obfuscated credentials |
| **Supply Chain Risk Management (SR)** | SR-6 | Supplier assessments — verifying vendor tools do not contain hardcoded secrets |
| **Configuration Management (CM)** | CM-7 | Least functionality — restricting which maintenance tools may be deployed on OT systems |

**Why NIST 800-82r3 matters here:** NIST 800-82r3 Section 6.2.3 explicitly calls out hardcoded credentials as a critical vulnerability class in OT environments. IA-5 requires that credentials not be embedded in software, while SR-6 recommends binary analysis of vendor-supplied tools as part of procurement security reviews. This challenge demonstrates exactly the kind of finding such a review would uncover.

</details>

## 💡 Hints

The password is not stored as plaintext. Look for byte arrays and XOR operations — a single constant key is XORed against each byte. Try `strings` first, then examine the comparison logic in a disassembler if needed.

## 🔍 Solution

The password is XOR-encoded in the binary with the key `0x42`. `strings` won't reveal it directly since no byte of the encoded password falls in the printable ASCII range after XOR.

**Option 1 — GDB (dynamic)**

Run the binary under GDB and break inside `check_credentials` after the decode loop executes. The decoded password sits in the `pw[]` buffer on the stack:

```bash
gdb ./plc_auth
(gdb) break check_credentials
(gdb) run
(gdb) next
(gdb) x/s pw
```

**Option 2 — Disassembly + offline solve (static)**

Open the binary in `objdump` or Ghidra, locate the `enc_pw` byte array and the XOR key `0x42` in the comparison logic, then invert the encoding in Python:

```python
enc_pw = [0x0F, 0x76, 0x73, 0x2C, 0x36, 0x71,
0x2C, 0x76, 0x2C, 0x21, 0x71, 0x63]
print(''.join(chr(b ^ 0x42) for b in enc_pw))
```

Enter the recovered password to print the flag.

**Flag:** `CybICS(x0r_1s_n0t_encrypti0n_4_PLC)`


Loading