Challenge Overview
Category: RF
Files: dist-ds_signpost.7z (a SigMF capture)
SigMF metadata:
core:datatype:cf32_lecore:sample_rate:500000core:frequency:915000000
The waterfall shows five clean transmissions at roughly:
-180 kHz-70 kHz+45 kHz+115 kHz+170 kHz
Each one has to be demodulated on its own. The last one carries the flag, but it’s password-protected.
1. -180 kHz — OOK Morse Code
After mixing the -180 kHz signal to baseband, taking the magnitude, and thresholding the envelope, the pulse timings are Morse code:
- Dot length: ~70 ms
- Dash length: ~220 ms
- Word gap: ~530 ms
Decoded text:
THIS FILE HAS 5 WAVESSo all five visible transmissions are in play.
2. -70 kHz — AM Voice Hint
The -70 kHz signal is AM-like. Envelope demodulation gives a repeated voice clip:
DQPSK stores data in phase changes. Decode each symbol by comparing it with the previous.That’s the hint for the final +170 kHz phase-encoded signal.
3. +45 kHz — FM Voice Hint
FM-demodulating the +45 kHz transmission gives another repeated voice clip:
Do you know APRS? APRS has a super secret password.This points at the packet-like bursts at +115 kHz.
4. +115 kHz — AX.25 / APRS Password
FM-demodulating the +115 kHz bursts gives Bell 202 AFSK. Decoding as 1200 baud AX.25 / APRS:
- mark / space tones:
1200 Hz/2200 Hz - NRZI decode
- HDLC flag search and bit unstuffing
- AX.25 address and payload parse
The valid APRS frame was:
N0CALL-1>APCTF:>The password is dWt4Wxm6Xfn1ot02So the password is:
dWt4Wxm6Xfn1ot025. +170 kHz — DQPSK ZIP Payload
The +170 kHz signal is a four-state phase signal. After downconverting, the active burst has:
- symbol length:
200samples - symbol rate:
500000 / 200 = 2500baud - phases quantised to four quadrants
The hint from step 2 is exactly the trick: don’t use the absolute phases, diff them.
q = quantized_phase_symbolsd = (q[1:] - q[:-1]) % 4With the natural two-bit mapping:
0 -> 001 -> 012 -> 103 -> 11and prepending the first phase difference against a zero-phase reference, the recovered bytes start with:
50 4b 03 04That’s a ZIP file header. The reconstructed ZIP contains flag.txt, but it is password-protected. Plugging in the APRS password:
import zipfile
with zipfile.ZipFile("sig5_payload.zip") as z: print(z.read("flag.txt", pwd=b"dWt4Wxm6Xfn1ot02"))Output:
FLAG{R4D10_FR3Q_L1TTL3_M4Z3}Flag
FLAG{R4D10_FR3Q_L1TTL3_M4Z3}