Skip to main content

hideme picoCTF 2023 Solution

Analyze a PNG image to discover and extract a hidden archive containing the flag.

Published: April 26, 2023Updated: August 25, 2026

Description

Every file gets a flag.

The SOC analyst saw one image been sent back and forth between two people. They decided to investigate and found out that there was more than what meets the eye here.

Download the flag.png file from the artifacts server.

bash
wget https://artifacts.picoctf.net/c/260/flag.png

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
Not sure what binwalk does or when to use it? The Introduction to Steganography Tools post explains binwalk alongside zsteg, steghide, and Stegsolve.
  1. Step 1Analyze the PNG file with binwalk
    Observation
    The description says there is more to the PNG than meets the eye, which points at data embedded in the file rather than visible steganography. binwalk scans for magic-byte signatures and will reveal any appended archive.
    Run binwalk to identify embedded data in the PNG. Two ZIP local file headers show up: 0x9B3B is the zero-length entry that just records the secret/ directory, and 0x9B7C is the entry for secret/flag.png. The 0x9B7C entry is the one that holds the payload bytes; the central directory and the end-of-central-directory record sit further on, ending at 0xA7E7.
    bash
    binwalk flag.png
    DECIMALHEXDESCRIPTION
    00x0PNG image, 512 x 504, 8-bit/color RGBA, non-interlaced
    410x29Zlib compressed data, compressed
    397390x9B3BZip archive data, at least v1.0 to extract, name: secret/
    398040x9B7CZip archive data, at least v2.0 to extract, compressed size: 2944, uncompressed size: 3095, name: secret/flag.png
    429830xA7E7End of Zip archive, footer length: 22
    What didn't work first

    Tried: Run steghide extract -sf flag.png and enter an empty password when prompted

    steghide works on JPEG and BMP, hiding data in pixel values behind a passphrase, and knows nothing about an appended ZIP. It reports no extractable data, or fails quietly, because this PNG was never steghide-encoded. binwalk scans raw byte offsets for magic numbers, which is exactly how a polyglot gets found.

    Tried: Run zsteg flag.png looking for LSB-encoded hidden data

    zsteg reads least-significant-bit planes in PNG pixel data, a wholly different technique from appending a ZIP after the IEND chunk. It scans every bit plane and returns noise or nothing, because the payload sits past the end of the image data rather than inside it. binwalk finds the archive by matching its magic bytes at a raw offset.

    Learn more

    binwalk is a firmware and file analysis tool that scans a binary for known magic-byte signatures. It recognizes hundreds of file formats - ZIP, gzip, PNG, ELF, JPEG, and more - by comparing byte patterns at every offset against its signature database. When it finds a match, it reports the decimal and hexadecimal offset along with a human-readable description.

    This technique works because most file formats are self-delimiting: they start with a recognizable header (a "magic number") and often end with a trailer. A ZIP archive begins with the bytes PK\x03\x04; a PNG starts with \x89PNG\r\n\x1a\n. Concatenating a valid PNG with a valid ZIP produces a file that image viewers display correctly (they stop at the PNG IEND chunk) while ZIP-aware tools see the appended archive. This is a classic polyglot file technique used in both steganography and malware delivery.

    In digital forensics, binwalk is routinely applied to firmware dumps, memory images, and suspicious attachments to surface embedded executables, configuration files, or compressed archives. The -e flag extracts all recognized components automatically, making it a powerful first step in any file analysis workflow.

  2. Step 2Extract the embedded ZIP archive
    Observation
    binwalk reports ZIP archive entries at two offsets inside the PNG, holding a file at secret/flag.png. That confirms a polyglot, so run unzip directly on the image to recover the payload.
    Unzip the PNG file directly (you could also use binwalk -e flag.png):
    bash
    unzip flag.png
    What didn't work first

    Tried: Run 7z e flag.png -o./out or p7zip -d flag.png expecting it to extract the archive

    7z often handles polyglots, though some versions refuse the file outright when the leading bytes look like a PNG rather than a ZIP signature. unzip is more forgiving, because it seeks to the end-of-central-directory record at the tail and ignores whatever came before. If 7z balks, switch to unzip, which suits this layout exactly.

    Tried: Run binwalk -e flag.png and then look inside _flag.png.extracted/ for the flag directly

    binwalk -e does extract the archive, but it drops the carved bytes into offset-named subdirectories rather than anything called secret. You still have to walk that extracted tree to find the inner image. Running unzip directly reproduces the original layout with none of the extra directories.

    Learn more

    Because the PNG file is simultaneously a valid ZIP archive (a polyglot), standard tools that look for the ZIP central directory at the end of the file will happily extract it. unzip finds the end-of-central-directory record regardless of what precedes it, so unzip flag.png works exactly like unzip archive.zip.

    Alternatively, binwalk -e flag.png carves out all detected archives and writes them to a _flag.png.extracted/ directory. Both methods achieve the same result; the direct unzip call is slightly faster since binwalk would need to re-scan. In real forensic workflows, binwalk -e is preferred because it handles nested archives (archives within archives) and formats other than ZIP automatically.

  3. Step 3Navigate and view the flag
    Observation
    unzip produces a secret directory holding flag.png, matching the entry names binwalk listed. The flag is drawn as visible text inside that inner image, so it is read by looking at the picture rather than by scanning the bytes.
    Change to the secret directory and verify the file is a real PNG, then open it. The flag is drawn into the pixels as visible text, so it has to be read with an image viewer or OCR rather than pulled out with strings.
    bash
    cd secret
    bash
    file flag.png
    bash
    xdg-open flag.png

    Expected output

    flag.png: PNG image data, 600 x 50, 16-bit grayscale, non-interlaced
    Any viewer will do (xdg-open flag.png, eog flag.png, or transfer it to your local machine via scp). Do not reach for strings flag.png | grep -i pico here: the flag is painted into the pixel data, not stored as a literal text chunk, so strings returns nothing. On a headless box or WSL, run tesseract flag.png stdout for OCR instead.
    Learn more

    The extracted secret/flag.png is a separate, independent image file that contains the flag rendered as visible text. This two-layer approach - hiding a file-within-a-file, where the inner file is itself an image - is a straightforward demonstration of steganography by appending (distinct from bit-plane steganography where data is hidden within pixel values).

    On headless servers or WSL environments where GUI tools aren't available, tesseract secret/flag.png stdout (OCR) is the way to turn those pixels into text. strings secret/flag.png only helps when a flag is stored as a literal text chunk, which is not the case here, so a purely visual flag like this one is best handled by OCR or by transferring the file to a local machine with scp and opening it there.

Interactive tools
  • StegallDrop any file and Stegall runs every applicable steg technique in parallel: LSB sweeps, bit planes, spectrograms, polyglot carving, metadata, whitespace decode, and a 6-layer base/ROT/XOR/zlib cascade. Recursively unpacks results and surfaces flag matches.
  • Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
  • Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.

Flag

Reveal flag

picoCTF{Hiddinng_An_i...d9f6587}

The flag is displayed in the image and can be seen with an image viewer.

Key takeaway

Polyglot files exploit the fact that most parsers read only as far as they need and stop at the first valid end marker, ignoring whatever trails behind. Append a ZIP after a PNG's IEND chunk and image viewers render the picture normally while unzip extracts the payload intact. The technique shows up in malware delivery, smuggling executables inside images past content filters, and in forensics, where binwalk surfaces embedded archives in firmware dumps, email attachments, and memory images.

Related reading

Useful tools for Forensics

Where to go next