write-up: IoT/Observe_The_Wired/README.md

This commit is contained in:
Eun0us 2026-03-26 17:33:37 +00:00
parent 30bd8dfd02
commit 9844d09683

View File

@ -1,52 +1,154 @@
# Observe The Wired -- Solution
# Observe The Wired
## Overview
CoAP node with observable stream. Recover fragments, decode the firmware blob, then POST the maintenance key.
| Field | Value |
|-------|-------|
| Category | IoT |
| Difficulty | Medium-Hard |
| Points | — |
| Author | Eun0us |
| CTF | Espilon 2026 |
## Steps
---
## Description
An IoT module from Clinique Sainte-Mika (Room 013) communicates via **CoAP** on the
WIRED-MED network. The stream seems stable... but the observation layer hides a key fragment.
*In The Wired, only observers hear the truth.*
Explore the CoAP resources, observe the stream, reconstruct the key, decode the firmware
blob, and open the maintenance channel.
- CoAP: `udp/<host>:5683`
Format: **ESPILON{flag}**
---
## TL;DR
Discover CoAP resources with a `.well-known/core` GET. Collect fragments A, B, C from
`/status`, `/telemetry/heart`, and the observable `/wired/stream`. Concatenate to build
XOR key `WIREDLAIN23`. Download and decode the firmware blob from `/archive/firmware`.
POST the maintenance key `0BS3RV3-L41N-23` to unlock and get the flag.
---
## Tools
| Tool | Purpose |
|------|---------|
| `coap-client` (libcoap) | CoAP GET, observe, POST |
| Python 3 | XOR decode, base64 |
---
## Solution
### Step 1 — Discover resources
1. Discover resources
```bash
coap-client -m get coap://HOST/.well-known/core
coap-client -m get coap://<HOST>/.well-known/core
```
2. Get fragments A and B
```bash
coap-client -m get coap://HOST/status
coap-client -m get coap://HOST/telemetry/heart
Returns a comma-separated list of resource links (RFC 6690 format):
```
</status>,</telemetry/heart>,</telemetry/temp>,
</wired/stream>;obs,</archive/firmware>,
</maintenance/unlock>
```
3. Observe the stream for fragment C
```bash
coap-client -m get -s 30 -o coap://HOST/wired/stream
```
Capture the JSON notification that includes `fragment_c`.
> 📸 `[screenshot: .well-known/core response listing all CoAP resources]`
### Step 2 — Get fragment A
```bash
coap-client -m get coap://<HOST>/status
```
Response includes: `fragment_a: WIRED`
### Step 3 — Get fragment B
```bash
coap-client -m get coap://<HOST>/telemetry/heart
```
Response includes: `fragment_b: LAIN`
### Step 4 — Observe the stream for fragment C
Subscribe to the observable resource for 30 seconds:
```bash
coap-client -m get -s 30 -o observe_out.txt coap://<HOST>/wired/stream
```
Among the periodic notifications, one JSON payload contains:
```json
{"fragment_c": "23", "node": "013"}
```
> 📸 `[screenshot: observable stream notification containing fragment_c value]`
### Step 5 — Build the XOR key
4. Build XOR key
Concatenate fragments in order A + B + C:
```
WIRED + LAIN + 23 = WIREDLAIN23
```
5. Download firmware blob
```bash
coap-client -m get coap://HOST/archive/firmware
```
Save the base64 data between `FIRMWARE_B64_BEGIN` and `FIRMWARE_B64_END` into `firmware.b64`.
### Step 6 — Download and decode the firmware blob
6. Decode the blob
```bash
python3 decode.py firmware.b64
coap-client -m get coap://<HOST>/archive/firmware
```
The JSON includes `maintenance_key`.
7. Unlock and get the flag
```bash
coap-client -m post -e '0BS3RV3-L41N-23' coap://HOST/maintenance/unlock
The response is a text payload with base64 between markers:
```
FIRMWARE_B64_BEGIN
<base64 data>
FIRMWARE_B64_END
```
Save and decode:
```python
import base64, json
with open("firmware.b64") as f:
b64_data = f.read().strip()
raw = base64.b64decode(b64_data)
# XOR with key WIREDLAIN23
key = b"WIREDLAIN23"
decoded = bytes(b ^ key[i % len(key)] for i, b in enumerate(raw))
config = json.loads(decoded.decode())
print(config["maintenance_key"])
# 0BS3RV3-L41N-23
```
> 📸 `[screenshot: Python script printing the maintenance key from the decoded firmware blob]`
### Step 7 — Unlock and get the flag
```bash
coap-client -m post -e "0BS3RV3-L41N-23" coap://<HOST>/maintenance/unlock
```
The response contains the flag.
> 📸 `[screenshot: CoAP POST response returning the flag]`
---
## Flag
`ESPILON{c0ap_0bs3rv3_th3_w1r3d}`
## Author
Eun0us
`ESPILON{c0ap_0bs3rv3_th3_w1r3d}`