Skip to main content

St3g0 picoCTF 2022 Solution

zsteg sweeps every bit plane and channel order at once, and one of those combinations yields the embedded flag.

Published: July 20, 2023Updated: August 25, 2026

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{...}.

bash
file pico.flag.png
bash
zsteg pico.flag.png
bash
zsteg pico.flag.png > output.txt && grep -oE 'picoCTF\{[^}]+\}' output.txt

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it

Run file pico.flag.png first to confirm what you're looking at, then pick the right tool by file type:

  • PNG → reach for zsteg first (lossless, perfect for LSB).
  • JPEG → try steghide extract (with the passphrase or empty), since LSB doesn't survive lossy compression.
  • Unknown / arbitrary binarybinwalk and xxd | head to 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.

  1. Step 1Enumerate hidden channels
    Observation
    The challenge provides a PNG, and PNG is losslessly compressed, which makes least-significant-bit steganography viable. zsteg scans every LSB channel permutation in a PNG, so run it first.
    zsteg pico.flag.png automatically 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 and expects a passphrase, so on a passphrase-less PNG it either refuses or returns nothing. zsteg is built for LSB steganography in PNGs and tries every common bit-plane and channel combination on its own.

    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.

  2. Step 2Capture the flag
    Observation
    zsteg prints results for many channel combinations at once. Pipe the output through grep for the picoCTF{ pattern so the right line does not get lost in 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, run strings for readable text, try binwalk -e to extract embedded files, check LSB with zsteg (PNG) or steghide 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.

Key takeaway

Digital image formats store pixel data in discrete channels; the least significant bits contribute almost nothing to visual fidelity but can carry a hidden payload without perceptible change. LSB steganography is detected and extracted by tools like zsteg and steghide, which scan image channels for statistical anomalies or try known passwords. PNG is the format of choice because its lossless compression preserves every bit exactly, whereas JPEG's lossy compression destroys hidden data during encoding. Real-world attackers have embedded malware command-and-control instructions inside ordinary-looking images posted to public platforms to evade network-level detection.

Related reading

Tools used in this challenge

Where to go next