# Cyberia Grid

| Field | Value |
|-------|-------|
| Category | OT |
| Difficulty | Medium-Hard |
| Points | 500 |
| Author | Eun0us |
| CTF | Espilon 2026 |

---

## Description

Cyberia is not just a nightclub. An industrial PLC controller manages the building power
infrastructure over EtherNet/IP.

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.

Read the tags. Find the hidden data. The Psyche Processor awaits activation.

- EtherNet/IP: `tcp/<host>:44818`

Format: **ESPILON{flag}**

---

## 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:
    # 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"
```

![cpppo client output listing all tag values including hidden ones](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/cyberia_tags.png)

**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 |

![Python calculation showing the four derived activation values](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/cyberia_calc.png)

### Step 4 — Activate the Psyche Processor

Write the derived values:

```python
with device(host="<HOST>", port=44818) as via:
    for i, val in enumerate([140, 95, 17, 4919]):
        via.write(via.parameter_substitution(f"Psyche_Processor[{i}]"), val)
```

### Step 5 — Wait one scan cycle and read the flag

After ~500ms (one PLC scan cycle):

```python
import time
time.sleep(0.6)

with device(host="<HOST>", port=44818) as via:
    flag = via.read("Decoded_Output")
    print(flag)

    # Also: Knights_Cipher[3] is now populated: 0x67 = 'g' → key = "Knig"
```

![Decoded_Output tag returning the flag after Psyche Processor activation](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/cyberia_flag.png)

### Key concepts

- `Zone_Basement_Power = 0` is the first hint that something is hidden underground
- 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}`
