← Back to Writeups
CUSTOMMediumSteganography

Radio Signal

XESXOR9/2/20262 min read
#steganography#custom#medium#frequency_detection#image_processing#zero_crossing

Radio Signal

Platform: hackerlab | Category: Steganography | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2025-12-23 | Status: Solved Techniques: frequency_detection, image_processing, zero_crossing

Summary

Task: WAV file with unknown radio station audio. Solution: Identified SSTV Robot 36 mode signal, implemented custom zero-crossing decoder to extract hidden image containing the flag.

Radio Signal — hackerlab

Description

A WAV file with an audio recording of an "unknown radio station" was provided. The goal is to extract hidden information.

Analysis

  1. Spectral analysis: When viewing the spectrogram of the audio file (e.g., in Audacity or using Python), a characteristic signal in the 1200-2300 Hz range is observed. The signal structure (sync pulses and frequency variations) indicates the use of SSTV (Slow Scan Television).
  2. Mode identification: The recording duration and data packet structure correspond to Robot 36 mode (color image 320x240, transmitted in approximately 36-37 seconds).
  3. Tool issues: Standard decoders (such as sstv or pysstv) may produce poor results or not work at all due to specific noise or timing deviations in the signal. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

For quality decoding, a custom script was implemented using the zero-crossing method to determine the instantaneous signal frequency. This method is resistant to certain types of distortion and allows accurate recovery of the luminance component.

Decoding algorithm:

  1. Read WAV file and normalize the signal.
  2. Determine instantaneous frequency through intervals between zero-line crossings.
  3. Map frequencies (1500-2300 Hz) to pixel brightness values (0-255).
  4. Synchronize by horizontal pulses (usually 1200 Hz).
  5. Assemble the 320x240 image. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Implementation example (conceptual):

python
import numpy as np
from scipy.io import wavfile
from PIL import Image

def decode_sstv(filename):
    fs, data = wavfile.read(filename)
    if len(data.shape) > 1: data = data[:, 0]
    
    # Zero crossing detection for frequency determination
    zero_crossings = np.where(np.diff(np.sign(data)))[0]
    periods = np.diff(zero_crossings)
    freqs = fs / (2 * periods)
    
    # Robot 36 parameters
    width, height = 320, 240
    img = Image.new('L', (width, height))
    
    # Simplified frequency to pixel mapping (Y-channel)
    # 1500 Hz = Black, 2300 Hz = White
    pixels = np.clip((freqs - 1500) / 800 * 255, 0, 255).astype(np.uint8)
    
    # Line assembly logic with sync pulse handling...
    # (omitted for brevity)
    
    return img
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# After decoding, orientation correction was needed
# img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.FLIP_TOP_BOTTOM)

Image processing:

After initial decoding of the luminance component (Y-channel), a noisy image was obtained. Main improvement steps:

  1. Orientation correction: The image was mirrored and flipped.
  2. Contrast enhancement: Using adaptive threshold filtering to highlight text.
  3. Flag reading: Text in leet-speak style was visible on the image. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍