Category: Signal Processing / Misc
Difficulty: Hard
Download Lines of Contact.rar - Try to solve it yourself before reading the writeup!
Youâre aboard a deep-space relay station when an incoming capture hits your buffer: a mono audio recording labeled â0xfunâ. The analysts insist itâs alien. But the encoding style feels familiar â like something humanity would send when it wanted to be understood without sharing a language. Dig into the signal, recover what itâs really carrying, and extract the flag.
This is an analog âpictures in audioâ challenge (Golden Recordâstyle raster), but youâre not told that up front.
Open ctf_record.wav in Audacity (or any waveform viewer) and zoom in.
There are repeating deep negative spikes at regular-ish intervals. That pattern is your first clue: real noise doesnât produce clean periodic âeventsâ like that.
Those spikes look like a line sync pulse: something that marks âstart of a line.â
If thereâs a repeating sync, the classic structure is:
[sync pulse][signal payload][sync pulse][signal payload]...
If you stack payloads line-by-line, you get an image. This is the âahaâ: treat the audio as scanlines.
Take the audio samples and look at their distribution. Sync pulses are the most negative plateau in the whole file.
A robust approach:
m = min(audio)thr = 0.7 * maudio < thrYou get a list of sync start indices: starts[].
Compute:
diffs = starts[i+1] - starts[i]
During picture regions, diffs will cluster tightly around a nominal value (small drift is normal).
Use: nominal_line = median(diffs) (after ignoring huge gaps)
There will be big gaps in diffs between picture segments (preamble / marker / separator).
Find indices where diffs > 3 * nominal_line and split starts[] into chunks (segments). Each chunk with lots of lines is a âpicture.â
For each line:
start + sync_len to next_start as the âvideo payloadâsync_len from the tight cluster of long run lengths: sync_len = median(long_run_lengths)payload = audio[start + sync_len : next_start]median(payload_length) to handle slight time driftConvert each resampled payload into a row. Stack rows in order â 2D array. Normalize brightness robustly using percentiles (1%â99%). Save as PNG.
One segment should look like a calibration image (circle or obvious shape). The next contains the flag.
Once the flag image appears, read it and submit.