$ / 3 min read/forensics
Ghost in the Machine
Every packet in the capture is byte-identical. The message is in the gaps between them, and the source ports spell out the XOR key.
- section
- CSAW26
- event
- ctf.csaw.io ↗
- category
- forensics
- status
- ● solved
- provided
- capture.pcap
Summary
Every packet in the capture is identical, so nothing is carried in the bytes. The message lives in the gaps between packets, and the XOR key that unlocks it is spelled out by the source ports.
1. The capture
504 UDP packets, one direction only:
- every payload is the literal
PING - every
IP.lenis 32 IP.idis pinned at 4919 (0x1337)
Nothing varies except TTL (64 or 113), source port, and arrival time.
2. Separating signal from noise
Of 121 distinct source ports, 6 carry 64–65 packets each and the other 115 carry one to three. Keeping only the six busy ports leaves 385 real packets; the 115 stragglers are chaff.
3. The key
The six real ports, in first-seen order, are a direct ASCII encoding:
| Port | minus 40000 | ASCII |
|---|---|---|
| 40115 | 115 | s |
| 40104 | 104 | h |
| 40052 | 52 | 4 |
| 40100 | 100 | d |
| 40111 | 111 | o |
| 40119 | 119 | w |
→ sh4dow
4. The covert channel
385 packets give 384 inter-arrival deltas, falling into two clean, non-overlapping bands:
- 245 short gaps, 35.5–64.8 ms
- 139 long gaps, 135.1–164.8 ms
Threshold at 100 ms, map long → 1 and short → 0, pack MSB-first into bytes,
then XOR with the repeating key.
bits = "".join('1' if x >= 100 else '0' for x in deltas)
ct = bytes(int(bits[i:i+8], 2) for i in range(0, len(bits), 8))
flag = bytes(ct[i] ^ b'sh4dow'[i % 6] for i in range(len(ct)))
Decoy
TTL also varies two ways (64/113) and looks like an obvious bit channel. Decoding it yields nothing.
Scripts: ~/ctf/work/pcap/ (an.py, t.py, t2.py)
## challenge files
7 files · 93 KB- an.py
- capture.pcap
- dec.py
- fixed.pcap
- t.py
- t2.py
- original/