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.
Setup
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
pip3 install numpy pillow pysoundfile scipy# Clone the sstv Python decoder from GitHubSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1
Decode the SSTV audio files with PythonObservationI 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.pythonpython3 sstv_decode.py message.wav -o decoded_message.pngpythonpython3 sstv_decode.py clue1.wav -o clue1.pngpythonpython3 sstv_decode.py clue2.wav -o clue2.pngpythonpython3 sstv_decode.py clue3.wav -o clue3.pngExpected 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.
Step 2
Read the clue images to find the steghide passwordObservationI 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.
Step 3
Extract the hidden data with steghideObservationI 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.bashsteghide extract -sf message.wav -p 'hidden_stegosaurus'bashcat steghide_output.txtWhat 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 passwordextracts data hidden with steghide. The-sfflag specifies the stego file, and-pprovides 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.