Skip to content

Commit 347e233

Browse files
authored
Create tetoris-writeup.mdx
1 parent fd422a1 commit 347e233

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

data/blog/tetoris-writeup.mdx

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---
2+
title: 'Tetoris'
3+
date: '2025-12-04'
4+
tags: ['hardware']
5+
draft: false
6+
summary: 'Write-up for the Tetoris challenge.'
7+
authors: ['elure']
8+
---
9+
10+
## Challenge description
11+
12+
**Name:** Tetoris
13+
**Category:** Hardware
14+
**Difficulty:** Easy
15+
16+
> This challenge is straightforward, no tricks. A logic analyzer was connected to the UART port of a device, can you see what it prints?
17+
18+
We’re given a single file: `challenge.sr` (a Sigrok/PulseView session).
19+
20+
Goal: decode the UART traffic and recover the printed text (the flag).
21+
22+
---
23+
24+
## 1. Open the capture
25+
26+
Since the file ends in `.sr`, it’s a Sigrok session. The easiest workflow:
27+
28+
1. Install **PulseView** (Sigrok GUI).
29+
2. Open `challenge.sr`.
30+
3. You should see **one digital channel** (named something like `uart`).
31+
32+
---
33+
34+
## 2. Identify UART settings (baud rate)
35+
36+
From the capture metadata (PulseView also shows this), the sample rate is **1 MHz**.
37+
38+
UART is asynchronous, so we need the **bit time**. A quick way:
39+
40+
- Zoom in on a start bit (idle high → falling edge to low).
41+
- Measure the width of the smallest repeated pulse length.
42+
43+
In this capture, the most common edge-to-edge spacing is **~104 samples**.
44+
45+
At **1 MHz**, that’s:
46+
47+
- `104 samples ≈ 104 µs per bit`
48+
- `baud ≈ 1 / 104e-6 ≈ 9615` → closest standard rate is **9600 baud**
49+
50+
So we use **9600 baud**.
51+
52+
---
53+
54+
## 3. Decode in PulseView (UART)
55+
56+
1. Click **Add protocol decoder**
57+
2. Select **UART**
58+
3. Configure:
59+
- **RX channel:** the only channel (`uart`)
60+
- **Baud rate:** `9600`
61+
- **Data bits:** `8`
62+
- **Parity:** `None`
63+
- **Stop bits:** `1`
64+
- **Bit order:** `LSB first` (default UART)
65+
66+
PulseView will immediately populate the decode row with bytes / ASCII.
67+
68+
Reading the decoded ASCII stream yields the flag.
69+
70+
---
71+
72+
## Flag
73+
74+
```text
75+
CTF{UART_1s_th3_b4ckb0n3_0f_s3r14l_d4t4_tr4nsm1ss10n}
76+
```
77+
78+
---
79+
80+
## Bonus: decode without GUI (Python)
81+
82+
If you don’t want PulseView, `.sr` is just a zip. The logic samples are raw 0/1 bytes, so we can decode UART by sampling mid-bit at 9600 baud.
83+
84+
```python
85+
import zipfile
86+
import numpy as np
87+
88+
BIT_SAMPLES = 104 # 1 MHz / 9600 ≈ 104 samples per bit
89+
90+
def decode_uart_loose(sig, bit_samples=BIT_SAMPLES, data_bits=8):
91+
n = len(sig)
92+
i = 0
93+
out = []
94+
95+
while i < n - 2:
96+
# falling edge = start bit
97+
if sig[i] == 1 and sig[i+1] == 0:
98+
t0 = i + 1
99+
100+
# start bit midpoint must be low
101+
mid_start = t0 + bit_samples // 2
102+
if mid_start >= n or sig[mid_start] != 0:
103+
i += 1
104+
continue
105+
106+
# sample 8 data bits at 1.5, 2.5, ..., 8.5 bit-times
107+
bits = []
108+
ok = True
109+
for b in range(data_bits):
110+
idx = int(round(t0 + bit_samples * (1.5 + b)))
111+
if idx >= n:
112+
ok = False
113+
break
114+
bits.append(int(sig[idx]))
115+
116+
if not ok:
117+
break
118+
119+
val = sum(bit << b for b, bit in enumerate(bits))
120+
out.append(val)
121+
122+
# jump past the frame (start + 8 data + stop)
123+
i = int(round(t0 + bit_samples * 10))
124+
continue
125+
126+
i += 1
127+
128+
return bytes(out)
129+
130+
with zipfile.ZipFile("challenge.sr", "r") as z:
131+
logic = z.read("logic-1-1")
132+
133+
sig = (np.frombuffer(logic, dtype=np.uint8) & 1).astype(np.uint8)
134+
msg = decode_uart_loose(sig).decode("ascii", errors="replace")
135+
print(msg)
136+
```
137+
138+
Output:
139+
140+
```text
141+
CTF{UART_1s_th3_b4ckb0n3_0f_s3r14l_d4t4_tr4nsm1ss10n}
142+
```
143+
144+
(We decode “loose” because captures sometimes end mid-stop-bit; the last byte can still be recovered reliably.)

0 commit comments

Comments
 (0)