Description
A PNG hides data in its least significant bits. Run zsteg (or similar tools) to uncover the embedded picoCTF flag.
Verify the file is actually a PNG with file pico.flag.png (PNG image data, ...) before reaching for zsteg.
Install zsteg (e.g., gem install zsteg) or use a prebuilt binary.
Run zsteg against the PNG and scan the reported channels for picoCTF{...}.
file pico.flag.pngzsteg pico.flag.pngzsteg pico.flag.png > output.txt && grep -oE 'picoCTF\{[^}]+\}' output.txtSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Run file pico.flag.png first to confirm what you're looking at, then pick the right tool by file type:
- PNG → reach for
zstegfirst (lossless, perfect for LSB). - JPEG → try
steghide extract(with the passphrase or empty), since LSB doesn't survive lossy compression. - Unknown / arbitrary binary →
binwalkandxxd | headto look for embedded files and magic headers before assuming pixel-level steganography.
For the broader landscape, see the Steganography in CTF guide and the Introduction to Steganography Tools, which covers zsteg, steghide, stegcracker, binwalk, and Stegsolve in depth.
Step 1
Enumerate hidden channelsObservationI noticed the challenge provides a PNG file named pico.flag.png, and PNG uses lossless compression, which suggested that least-significant-bit steganography was involved and that zsteg, the standard tool for scanning all LSB channel permutations in PNGs, should be the first thing to run.zsteg pico.flag.pngautomatically checks common LSB encodings. One of the entries prints the flag outright.What didn't work first
Tried: Running steghide instead of zsteg on the PNG file.
steghide targets JPEG and BMP formats and requires a passphrase. On a PNG with no passphrase it will either refuse to extract or return nothing useful. zsteg is the right tool for LSB steganography in PNG files because it tries all common bit-plane and channel combinations automatically.
Tried: Opening the image in a hex editor and scrolling through raw bytes looking for picoCTF manually.
LSB-encoded data is scattered across many pixels one bit at a time, so it never appears as readable ASCII in a hex dump. The bits must be reassembled in the correct channel order and bit depth before the text becomes visible, which is exactly what zsteg automates.
Learn more
LSB steganography hides data in the least significant bits of pixel color values. In a 24-bit RGB image, each pixel has three channels (R, G, B) each with 8 bits (0-255). Changing the last 1-2 bits alters the color value by at most 1-3 out of 255 - a difference invisible to the human eye but detectable programmatically.
zsteg is a Ruby tool that automatically tests many LSB configurations: different bit depths (1-8 bits), different channel orders (R, G, B, alpha), different read orders (row by row, column by column, etc.), and different encodings. It checks for known file signatures and readable strings in all combinations, making it far faster than manual analysis.
PNG is the preferred format for LSB steganography because it uses lossless compression - every pixel value is stored exactly. JPEG uses lossy compression, which modifies pixel values during encoding, destroying hidden LSB data. This is why steganography tools almost always specify PNG format for the output carrier image.
Step 2
Capture the flagObservationI noticed zsteg prints results for many different channel combinations at once, which suggested piping the output through grep with the picoCTF{ pattern to avoid missing the correct line among the noise.Optionally redirect zsteg's output to a file and use grep/cut to isolate the picoCTF line.What didn't work first
Tried: Copying the entire zsteg output and searching it visually line by line instead of using grep.
zsteg can produce dozens of lines for different channel configurations. Scrolling manually is error-prone and slow. Piping to grep with the pattern 'picoCTF{' or using the provided grep command pinpoints the correct line immediately.
Learn more
Beyond zsteg, the steganography forensics toolkit includes: steghide (hides data in JPEG/BMP using passphrase encryption), stegsolve (Java GUI for visualizing individual bit planes and channel combinations), binwalk (detects and extracts embedded files based on magic bytes), and exiftool (reads/writes metadata in image files).
In CTF competitions, when you receive an image, the standard checklist is: check file metadata with
exiftool, runstringsfor readable text, trybinwalk -eto extract embedded files, check LSB withzsteg(PNG) orsteghide extract(JPEG), and examine individual bit planes with stegsolve. Each tool covers different hiding techniques.Real-world steganography has been used in malware command-and-control: malware downloads seemingly innocent images from social media, extracts hidden commands from pixel data, and executes them - a technique that evades network monitoring because the traffic looks like ordinary image downloads. This technique is called stegomalware.
Interactive tools
- Image Metadata ViewerRead EXIF, XMP, JPEG comments, and PNG tEXt / iTXt / zTXt chunks from images entirely in the browser. Highlights flag-like values.
Flag
Reveal flag
picoCTF{7h3r3_15_n0_5p00n_...}
The trailing 8-hex-character suffix is generated per challenge instance (e.g. 96ae0ac1 or 1b8d71db). If zsteg is not available, tools like stegsolve or binwalk can also reveal the payload, though with more manual work.