Blkhurst

February 19 2025

RF Capture #2

Stage 3 Area 1

We're given an RF capture along with the hint:

"Reverse using GNURADIO."

Before learning to use GNU Radio, I started with my typical workflow. Opening the capture in Inspectrum showed four distinct signals:

At this point, the 2-FSK and ASK signals were textbook examples of their modulation, but the other two were much harder to identify. I started by demodulating the signals I could identify before tackling the ambiguous ones.

Demodulating the first two signals

-347.5 kHz (2-FSK)

This signal was textbook 2-FSK (frequency shift keying), two distinct frequencies with clear separation and very little energy in between. Inspectrum's frequency plot showed sharp, digital-like transitions between two levels, making it easy to measure the symbol rate (2.5 kBd) and export the bitstream. Decoding it produced:

UUThis is not the signal you were looking for!!!!\n

+50 kHz (ASK)

This signal was ASK/OOK (amplitude shift keying), a single carrier turning on and off in clear bursts. In Inspectrum, the amplitude plot switched between two levels, and I measured the symbol rate at 2.5 kBd, although it was too noisy to reliably threshold.

I later revisited this signal after learning the basics of GNU Radio, where I was able to easily filter and demodulate. Decoding resulted in the same UUThis is not the signal message.

Understanding GNU Radio

Up to this point I'd been relying on Inspectrum, this is when I decided GNU Radio would be required to solve the remaining signals.

To learn, I went back to the previous RF challenge (Stage 2 Area 3) to re-create Inspectrum's signal processing pipeline.

Below is an overview of the core signal-processing stages:

Identifying the remaining signals

The remaining -150 kHz and +450 kHz signals didn't look like textbook examples of anything I'd seen before. Rather than guessing, I built a small GNU Radio identification flowgraph to rule out modulations.

For each signal, I exposed sliders for frequency, filters, deviation/gain, then compared:

We can rule out ASK since both signals maintain a relatively constant magnitude, showing no indication of two-level switching.

We can rule out PSK because even with carrier recovery, the constellation never collapses into stable clusters (two for BPSK, four for QPSK). To confirm this wasn't a configuration issue, I generated my own PSK signal, both standard and RRC-shaped, and merged it into the capture; those produced the expected clusters, while these signals did not.

That left frequency-based modulation.

Continuous-phase / pulse-shaped FSK

The quadrature demod output clearly contained structure, but it wasn't the clean square-like waveform of the previous BFSK signal. Instead, transitions were rounded, and the spectrum appeared as a blurred mound rather than two cleanly separated tones.

I learned these characteristics are typical of continuous-phase and/or pulse-shaped FSK variants such as Gaussian-shaped FSK (GFSK), especially when combined with the fact these signals occupy a much narrower bandwidth.

I decided to generate my own GFSK signal to compare, and the result looked almost identical. I was confident both signals belonged to the CPFSK / GFSK family. The next step was to tune the frequency deviation, before attempting demodulation.

Tuning deviation via discriminator normalisation

gain=fs2πΔfgain = \frac{f_s}{2\pi\Delta f}

GNU Radio's Quadrature Demod has a gain term that depends on the expected frequency deviation, where fsf_s is the (decimated) sample rate and Δf\Delta f is the frequency deviation.

Since there were no clearly separated mark/space tones, I could not reliably measure the deviation using the FFT. That's when I discovered a workflow to estimate frequency deviation by normalising the discriminator output:

  1. Mix to baseband and isolate the signal (Xlating FIR)
  2. Apply Quadrature Demod
  3. Add a light smoothing low-pass filter to identify plateaus.
  4. Sweep Δf\Delta f until the smoothed discriminator output sits consistently around ±1\pm 1.

Using this method, both signals landed at roughly Δf625 Hz\Delta f \approx 625\text{ Hz}. With Rs2500R_s \approx 2500 baud, we can compute the CPFSK modulation index:

h=2ΔfRs=26252500=0.5h = \frac{2 \Delta f}{R_s} = \frac{2 \cdot 625}{2500} = 0.5

This value is significant. MSK (minimum shift keying) is the special CPFSK case where the modulation index h=0.5h=0.5, and GMSK is MSK with Gaussian pulse shaping. Combined with:

then GMSK is a very plausible fit.

Demodulating the remaining signals

With the modulation understood, both remaining signals can be solved with the same demodulation chain:

Note: GNU Radio's GMSK Demod block with a gain of 0.1 and a leading low-pass with a cutoff of 2 kHz also demodulates both signals perfectly.

-150 kHz (GMSK-like, Manchester encoded)

This signal was Manchester encoded. I wrote a small python script that split each transmission and decoded it, resulting in the same decoy message: UUThis is not the signal you were looking for!!!!\n

+450 kHz (GMSK-like)

Unlike the -150 kHz signal, this one was not Manchester encoded, but it was slightly more challenging since the discriminator output idled centrally, causing noise for the binary slicer. A small frequency shift (200 Hz) was enough to stabilise it and make the slicer reliable.

With that adjustment, the transmission decoded cleanly and finally revealed the real key, challenge complete.

Key:RebootASRM+SuperSpace\n\n