# The Wired

| Field | Value |
|-------|-------|
| Category | Intro |
| Difficulty | Medium |
| Points | 400 |
| Author | Eun0us |
| CTF | Espilon 2026 |

---

## Description

Something was interrupted.

The agents are still flashed. The link is broken. The devices continue to boot, identify
themselves, and wait for instructions they never receive.

You have gained access to a machine that was once used to administer a fleet of ESP32-based
agents. Logs, firmware dumps, technical notes — everything is still there.

The coordination point is still listening.

If you can understand how the agents communicate, prove your identity, and complete the
handshake — the coordinator will tell you what it knows.

**Ports:**
- 1337: Navi Shell (investigation)
- 2626: C2 Coordinator

Format: **ESPILON{flag}**

*"No matter where you go, everyone's connected."*

---

## TL;DR

Read the files on the investigation machine (port 1337) to understand a 2-step ChaCha20 +
Protobuf C2 protocol. Extract the real crypto key from firmware ELF strings (avoid the
honeypot dev key). Impersonate device `ce4f626b` (the "Eiri_Master" root coordinator).
Send an `AGENT_INFO` message, capture the session token from the response, then send a
`CMD_RESULT` message with that token — all on the same TCP connection — to receive the flag.

---

## Tools

| Tool | Purpose |
|------|---------|
| `nc` | Connect to Navi Shell |
| Python 3 + `pycryptodome` | ChaCha20 encrypt/decrypt |
| `strings` / Ghidra | Extract key from ELF binary |
| Manual Protobuf encoding | Serialize AgentMessage |

---

## Solution

### Step 1 — Explore the investigation machine

```bash
nc <HOST> 1337
cat README_FIRST.txt
ls -la
```

Directories present: `notes/`, `comms/`, `dumps/`, `logs/`, `tools/`, `journal/`, `wired/`

**Critical files:**

- `notes/protocol.txt` — frame format:
  ```
  base64( ChaCha20( protobuf(AgentMessage) ) ) + '\n'
  ```
- `notes/derivation.txt` — ChaCha20 key is 32 bytes, nonce is 12 bytes, counter=0
- `notes/hardening.txt` — warns about a trap dev key at the bottom; Jan 17 journal entry
  confirms the key `Xt9Lm2Qw7KjP4rNvB8hYc3fZ0dAeU6sG` is planted bait
- `tools/devices.json` — lists all known device IDs with roles

![notes/protocol.txt showing the frame format](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_protocol.png)

### Step 2 — Identify the target device

Read `notes/eiri.txt` and `tools/devices.json`:

```
Device: ce4f626b
Alias:  Eiri_Master
Role:   root-coordinator
Status: quarantine
```

Regular devices receive a `heartbeat` response. Only `ce4f626b` triggers the flag path.

![devices.json showing the Eiri_Master entry with root-coordinator role](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_devices.png)

### Step 3 — Understand the handshake

From `comms/msg_ops_20260114.txt`:

1. Agent sends `AGENT_INFO` → coordinator replies `session_init` with a random token in `argv[0]`
2. Agent sends `AGENT_CMD_RESULT` with `request_id` = that token → coordinator replies with the flag

Both messages must go over the **same TCP connection**. The token is per-connection.

### Step 4 — Extract the ChaCha20 key

```bash
strings dumps/7f3c9a12/bot-lwip.elf | grep -E '^[A-Za-z0-9]{32}$'
strings dumps/7f3c9a12/bot-lwip.elf | grep -E '^[A-Za-z0-9]{12}$'
```

- Key (32 bytes): `7Kj2mPx9LwR4nQvT1hYc3bFz8dAeU6sG`
- Nonce (12 bytes): `X3kW7nR9mPq2`

Do **not** use the key found in `notes/hardening.txt` — it is a honeypot.

![strings output showing the real 32-character key](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_strings.png)

### Step 5 — Send the two-message handshake

```python
import base64, socket
from Crypto.Cipher import ChaCha20

HOST = "<HOST>"
PORT = 2626
KEY   = b"7Kj2mPx9LwR4nQvT1hYc3bFz8dAeU6sG"
NONCE = b"X3kW7nR9mPq2"

def encrypt_frame(plaintext):
    cipher = ChaCha20.new(key=KEY, nonce=NONCE)
    return base64.b64encode(cipher.encrypt(plaintext)) + b"\n"

def decrypt_frame(frame):
    raw = base64.b64decode(frame.strip())
    cipher = ChaCha20.new(key=KEY, nonce=NONCE)
    return cipher.decrypt(raw)

# Manually encode AgentMessage as protobuf
# field 1 (device_id) = "ce4f626b", field 2 (type) = 0 (INFO), field 5 (payload) = b"ce4f626b"
def encode_agent_info():
    dev_id = b"ce4f626b"
    msg = b""
    msg += b"\x0a" + bytes([len(dev_id)]) + dev_id   # field 1 = device_id
    msg += b"\x10\x00"                                  # field 2 = type 0 (INFO)
    msg += b"\x2a" + bytes([len(dev_id)]) + dev_id   # field 5 = payload
    return msg

with socket.create_connection((HOST, PORT)) as s:
    # MSG1 — AGENT_INFO
    s.sendall(encrypt_frame(encode_agent_info()))
    resp_raw = s.recv(4096)
    resp_pb = decrypt_frame(resp_raw)

    # Extract token from argv[0] in the Command protobuf response
    # (parse manually or use protobuf library)
    token = extract_token(resp_pb)

    # MSG2 — CMD_RESULT (type=4)
    def encode_cmd_result(token):
        dev_id = b"ce4f626b"
        msg = b""
        msg += b"\x0a" + bytes([len(dev_id)]) + dev_id
        msg += b"\x10\x04"                                      # type 4 = CMD_RESULT
        msg += b"\x22" + bytes([len(token)]) + token.encode()  # field 4 = request_id
        msg += b"\x2a" + bytes([len(dev_id)]) + dev_id
        return msg

    s.sendall(encrypt_frame(encode_cmd_result(token)))
    flag_resp = s.recv(4096)
    flag_pb = decrypt_frame(flag_resp)
    print(flag_pb)
```

The server replies:

```
Command {
    command_name = "flag"
    argv         = ["ESPILON{th3_w1r3d_kn0ws_wh0_y0u_4r3}"]
}
```

![solver output showing the decrypted flag response](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_solver.png)

### Things that will get you silently dropped

- Using the honeypot dev key from `hardening.txt`
- Sending a `device_id` not in the allowlist
- Using a valid but non-master device (returns `heartbeat`, not `flag`)
- Sending MSG2 on a **new** TCP connection (token is session-scoped)
- Wrong `type` in MSG2 (must be `4`)
- Wrong `request_id` (must match the token exactly)

---

## Flag

`ESPILON{th3_w1r3d_kn0ws_wh0_y0u_4r3}`
