From de91ac689c609ec51f958e826284723d80b9a213 Mon Sep 17 00:00:00 2001 From: Eun0us Date: Thu, 26 Mar 2026 17:33:37 +0000 Subject: [PATCH] write-up: IoT/Observe_The_Wired/README.md --- IoT/Observe_The_Wired/README.md | 162 ++++++++++++++++++++++++++------ 1 file changed, 132 insertions(+), 30 deletions(-) diff --git a/IoT/Observe_The_Wired/README.md b/IoT/Observe_The_Wired/README.md index d2233d3..123fb54 100644 --- a/IoT/Observe_The_Wired/README.md +++ b/IoT/Observe_The_Wired/README.md @@ -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/: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:///.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): + +``` +,,, +;obs,, + ``` -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:///status +``` + +Response includes: `fragment_a: WIRED` + +### Step 3 — Get fragment B + +```bash +coap-client -m get coap:///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:///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:///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 + +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:///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}`