Writeup: Signal Tap Lain - EspilonCTF (Hardware)
Description
A debug probe is capturing signals from Lain's NAVI. Three channels are being recorded, but what protocol is in use?
Capture the data, identify the protocol, and decode the message.
Solution
Step 1: Capture the Signal Data
Connected to the service using netcat:
nc espilon.net 38751 > capture.csv
The service streams CSV data with a header:
time_us,ch0,ch1,ch2
Three digital channels sampled over ~215,000 microseconds, totaling ~10,000 samples.
Step 2: Analyze the Channels
Examining the captured data revealed the following:
- ch0 — Toggles between 0 and 1 every 25 us (clock reference at 20 kHz)
- ch1 — Idles high (1), with transitions occurring at intervals of ~104.17 us
- ch2 — Secondary signal with irregular transitions (not meaningful ASCII)
The key observation: 104.17 us = 1/9600 seconds, which is the bit period for 9600 baud UART.
Step 3: Identify the Protocol
The protocol is UART (Universal Asynchronous Receiver-Transmitter) at 9600 baud, 8N1 (8 data bits, no parity, 1 stop bit).
UART characteristics confirmed:
- Idle state is HIGH (1)
- Start bit is LOW (0) — falling edge triggers byte reception
- 8 data bits transmitted LSB first
- Stop bit is HIGH (1)
Step 4: Decode the UART Data
Wrote a Python decoder that:
- Detects falling edges on ch1 (start bits)
- Samples the middle of each bit period (offset by half a bit period)
- Reads 8 data bits LSB-first
- Verifies the stop bit
def decode_uart(channel_idx, baud=9600):
bit_period = 1000000.0 / baud # 104.17 us
for each falling_edge on channel: # start bit detected
for bit in range(8):
sample_time = start + bit_period * (bit + 1) + bit_period / 2
byte_val |= (sample_at(sample_time) << bit) # LSB first
Step 5: Read the Message
The decoded output (repeated 3 times in the capture):
[WIRED-MED] maintenance_token=ESPILON{s1gn4l_t4p_d3c0d3d}
Flag
ESPILON{s1gn4l_t4p_d3c0d3d}