ESPILON-CTF-2026-Writeups/IoT/Observe_The_Wired/README.md
Eun0us 1c42421380 Add 107 terminal screenshots and replace all 📸 placeholders
- Generated screenshots for all 33 challenges (ESP, Hardware, IoT, OT, Misc, Web3)
- Replaced all 123 placeholder lines with actual PNG image references
- Cleaned duplicate images from previously partial updates
- All write-ups now have full illustrated solutions
2026-03-27 00:34:47 +00:00

3.4 KiB

Observe The Wired

Field Value
Category IoT
Difficulty Medium-Hard
Points
Author Eun0us
CTF Espilon 2026

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

coap-client -m get coap://<HOST>/.well-known/core

Returns a comma-separated list of resource links (RFC 6690 format):

</status>,</telemetry/heart>,</telemetry/temp>,
</wired/stream>;obs,</archive/firmware>,
</maintenance/unlock>

.well-known/core response listing all CoAP resources

Step 2 — Get fragment A

coap-client -m get coap://<HOST>/status

Response includes: fragment_a: WIRED

Step 3 — Get fragment B

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:

coap-client -m get -s 30 -o observe_out.txt coap://<HOST>/wired/stream

Among the periodic notifications, one JSON payload contains:

{"fragment_c": "23", "node": "013"}

observable stream notification containing fragment_c value

Step 5 — Build the XOR key

Concatenate fragments in order A + B + C:

WIRED + LAIN + 23 = WIREDLAIN23

Step 6 — Download and decode the firmware blob

coap-client -m get coap://<HOST>/archive/firmware

The response is a text payload with base64 between markers:

FIRMWARE_B64_BEGIN
<base64 data>
FIRMWARE_B64_END

Save and decode:

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

Python script printing the maintenance key from the decoded firmware blob

Step 7 — Unlock and get the flag

coap-client -m post -e "0BS3RV3-L41N-23" coap://<HOST>/maintenance/unlock

The response contains the flag.

CoAP POST response returning the flag


Flag

ESPILON{c0ap_0bs3rv3_th3_w1r3d}