Открытка от деда (Grandfather's Postcard)
Открытка от деда (Grandfather's Postcard)
Platform: duckerz | Category: Hardware | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-09 | Status: Solved Techniques: bit_sampling, uart_decoding, vcd_parsing
Summary
Files: postcard.vcd
Открытка от деда (Grandfather's Postcard) — duckerz
Description
Мой дедушка очень принципиальный и отказывается отправлять мне сообщения в WhatsApp, так что общаемся с помощью логического анализатора… Он передаёт данные через UART на скорости 9600 бод, 8 бит данных — без всяких твоих современных мессенджеров.
(Translation: My grandfather is very principled and refuses to send me messages on WhatsApp, so we communicate using a logic analyzer... He transmits data via UART at 9600 baud, 8 data bits - without any of your modern messengers.)
Files: postcard.vcd
Analysis
VCD Format
VCD (Value Change Dump) is a standard format for recording logic analyzer signals. The file contains:
- Header with metadata (timescale, variables)
- Timestamps with signal changes
File structure:
$timescale 1ns $end
$var wire 1 ! D0 $end
...
#0
1!
#104166
0!
...
UART Parameters
From the task description:
- Baud rate: 9600
- Data bits: 8
- Parity: none (standard)
- Stop bits: 1 (standard)
- Bit duration: 1,000,000,000 / 9600 ≈ 104166.67 ns
UART Protocol
- Idle state — HIGH (1)
- Start bit — LOW (0), falling edge signals frame start
- 8 data bits — transmitted LSB first (least significant bit first)
- Stop bit — HIGH (1)
___ ___ ___ ___ ___ ___ ___ ___ ___ ___
| |D0 |D1 |D2 |D3 |D4 |D5 |D6 |D7 | |
|___| | | | | | | | | |
START STOP
Solution
Decoding Algorithm
- Parse VCD file, extract signal transitions (time, value)
- Find falling edges (1→0) — these are start bits
- For each start bit, sample 8 data bits in the middle of each bit period
- Sampling time for bit N:
start_time + bit_duration * (1.5 + N) - Verify stop bit = HIGH
- Assemble bytes into a string
Python Solution
python read-only • copy allowed#!/usr/bin/env python3 """ UART decoder for VCD files duckerz CTF - Grandfather's Postcard """ def parse_vcd(filename): """Parse VCD file and extract signal transitions.""" transitions = [] current_time = 0 with open(filename, 'r') as f: for line in f: line = line.strip() if line.startswith('#'): # Timestamp line current_time = int(line[1:]) elif line == '0!': transitions.append((current_time, 0)) elif line == '1!': transitions.append((current_time, 1)) return transitions def build_signal(transitions): """Build a function that returns signal value at any time.""" def get_value(t): value = 1 # UART idle is HIGH for time, v in transitions: if time > t: break value = v return value return get_value def decode_uart(transitions, baud_rate=9600): """Decode UART signal from transitions.""" bit_duration = 1_000_000_000 / baud_rate # ns per bit get_signal = build_signal(transitions) # Find falling edges (start bits) falling_edges = [] prev_value = 1 for time, value in transitions: if time == 0: prev_value = value continue if prev_value == 1 and value == 0: falling_edges.append(time) prev_value = value decoded = [] last_frame_end = 0 for start_time in falling_edges: # Skip if this edge is within a previous frame if start_time < last_frame_end: continue # Sample 8 data bits in the middle of each bit period byte_value = 0 for bit_idx in range(8): # Sample at 1.5 + bit_idx bit periods from start sample_time = start_time + bit_duration * (1.5 + bit_idx) bit_value = get_signal(sample_time) byte_value |= (bit_value << bit_idx) # LSB first # Verify stop bit stop_time = start_time + bit_duration * 9.5 if get_signal(stop_time) == 1: decoded.append(chr(byte_value)) last_frame_end = start_time + bit_duration * 10 return ''.join(decoded) if __name__ == '__main__': transitions = parse_vcd('postcard.vcd') message = decode_uart(transitions) print(f"Decoded message: {message}")
Alternative Tools
- GTKWave — open VCD file, visually analyze the signal
- PulseView/sigrok — use built-in UART decoder:
- Open VCD file
- Add UART protocol
- Configure: 9600 baud, 8N1
- Get decoded data
Important Notes
- VCD stores only transitions — not continuous samples
- First transition (time=0) — initialization, not data
- UART transmits LSB first — least significant bit first
- Sampling in the middle of bit — provides jitter tolerance