m00nwalk2 picoCTF 2019 Solution

Published: April 2, 2026

Description

Revisit the first moonwalk transmission. This one has a hidden message inside - one decoded image contains clues and another contains the actual hidden flag, protected by a steganography password.

Download the WAV file(s) from the challenge.

Install the Python SSTV decoder from GitHub (pystemd/slowrx or similar sstv Python library).

Install steghide: sudo apt install steghide

bash
pip3 install numpy pillow pysoundfile scipy
bash
# Clone the sstv Python decoder from GitHub

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1
    Decode the SSTV audio files with Python
    Observation
    I noticed the challenge is titled 'm00nwalk2' and provides WAV files, which are the same signals used in the Apollo 11 moonwalk transmissions, suggesting SSTV audio encoding; decoding the WAV files with a Python SSTV library was the direct way to extract the hidden images.
    Use a Python SSTV library to decode the WAV file(s). The library auto-detects the SSTV mode (Scottie 1, Martin 1, etc.) and outputs image files. Decode all WAV files provided.
    python
    python3 sstv_decode.py message.wav -o decoded_message.png
    python
    python3 sstv_decode.py clue1.wav -o clue1.png
    python
    python3 sstv_decode.py clue2.wav -o clue2.png
    python
    python3 sstv_decode.py clue3.wav -o clue3.png

    Expected output

    picoCTF{the_answer_lies_hidden_in_plain_sight}
    What didn't work first

    Tried: Use QSSTV with a virtual audio loopback (e.g. PulseAudio loopback or VB-Cable) to decode the WAV file

    QSSTV requires a live audio input stream, so playing the WAV through a loopback device introduces timing drift and buffer underruns that corrupt the sync pulse, producing a skewed or entirely black image. The Python decoder reads sample arrays directly from the file without a loopback, so it receives a perfect bitstream and detects the VIS mode code reliably.

    Tried: Open the WAV file in Audacity and look for spectrogram patterns to manually read the image data

    The spectrogram view shows the frequency-time structure of SSTV audio but does not decode pixel color values - it only tells you that an SSTV signal is present. Manually mapping spectrogram intensities to pixel values is impractical for anything beyond a few pixels. A dedicated SSTV decoder is required to reconstruct the actual PNG output.

    Learn more

    SSTV (Slow Scan Television) encodes images as audio signals. Different SSTV modes (Scottie 1, Martin 1, Robot 36, etc.) use different image sizes, color orders, and timing. A Python decoder using scipy for signal processing can detect the mode automatically from the VIS code at the start of the audio.

  2. Step 2
    Read the clue images to find the steghide password
    Observation
    I noticed the SSTV decoding produced multiple images labeled as 'clue' files alongside the main message, which suggested the clue images were meant to be read for metadata or instructions, specifically the steghide password needed for the next layer.
    The decoded clue images contain three hints. Clue 1 gives the steganography password: 'hidden_stegosaurus'. Clue 2 hints at steganography in audio (the quieter you are the more you can hear). Clue 3 mentions a steganography tool website. Combined, the clues tell you to run steghide on the original WAV file with the password 'hidden_stegosaurus'.
    Learn more

    Steghide can hide data inside image and audio files. For WAV files, it embeds data in the least significant bits of the audio samples without significantly changing the sound. The embedded data is password-protected.

  3. Step 3
    Extract the hidden data with steghide
    Observation
    I noticed clue 2 hinted at audio steganography ('the quieter you are the more you can hear') and clue 3 referenced a steganography tool, while clue 1 explicitly gave the password 'hidden_stegosaurus', which together pointed to running steghide on the original message.wav file.
    Run steghide on the main WAV file using the password found in the clue images. The extracted file contains the flag.
    bash
    steghide extract -sf message.wav -p 'hidden_stegosaurus'
    bash
    cat steghide_output.txt
    What didn't work first

    Tried: Run steghide on the decoded PNG images instead of the original WAV file

    Steghide stores its payload in the stego carrier file that was used during embedding. The PNGs were produced by the SSTV decoder and contain only image data with no steghide payload. Running steghide extract on them returns 'could not extract any data' or a passphrase error. The flag is embedded in message.wav itself, which is the carrier steghide actually wrote to.

    Tried: Try steghide without the -p flag and enter a blank password when prompted

    Steghide uses password-based encryption (Rijndael) to protect the hidden payload. An empty passphrase produces a different key than 'hidden_stegosaurus', so decryption fails and steghide reports 'passphrase is not correct'. The correct password comes from the clue1.png image decoded in the previous step.

    Learn more

    steghide extract -sf file -p password extracts data hidden with steghide. The -sf flag specifies the stego file, and -p provides the passphrase. If no output filename is specified, steghide writes to the embedded filename. The extracted file contains the flag.

    This challenge layered two steganography techniques: SSTV audio encoding (to hide the clue images inside audio) and steghide (to hide the flag inside the original WAV). Understanding that clues are often themselves encoded requires checking every artifact in the challenge.

Flag

Reveal flag

picoCTF{the_answer_lies_hidden_in_plain_sight}

Decode the SSTV WAV files to get clue images, read the password 'hidden_stegosaurus' from clue 1, then run steghide extract on the main WAV file to get the flag.

Key takeaway

Layered steganography chains multiple covert channels so that defeating one layer only reveals instructions for the next. This mirrors real-world covert communication tradecraft where decoys and misdirection slow down an analyst. A forensic mindset requires treating every decoded artifact as a potential new container, not just a final answer. Password-protected steghide payloads inside SSTV audio inside a WAV file is a good example of how attackers can combine techniques that each seem innocuous to produce a well-hidden channel.

Related reading

Want more picoCTF 2019 writeups?

Useful tools for Forensics

What to try next