hideme picoCTF 2023 Solution

Published: April 26, 2023

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 1
    Analyze the PNG file with binwalk
    Observation
    I noticed the challenge description said there was 'more than what meets the eye' in the PNG, which suggested hidden data embedded inside the file rather than visible steganography, pointing me toward binwalk to scan for magic-byte signatures and reveal any appended archives.
    Run binwalk to identify embedded data in the PNG. Two offsets show up: 0x9B3B is the ZIP central-directory entry for the secret/ directory marker, and 0x9B7C is the actual file entry for secret/flag.png. The 0x9B7C entry is the one that holds the payload bytes.
    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 targets JPEG and BMP steganography and embeds data inside pixel values using a passphrase - it has no knowledge of appended ZIP archives. It will either report 'could not extract any data' or fail silently because the PNG is not a steghide-encoded file. binwalk is the right tool here because it scans raw byte offsets for magic-number signatures, which is exactly how a polyglot file is detected.

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

    zsteg analyzes least-significant-bit planes in PNG pixel data, which is a completely different hiding technique from appending a ZIP archive after the PNG IEND chunk. zsteg will scan all bit planes and likely output noise or nothing useful, because the hidden payload lives past the end of the image data - not inside it. binwalk finds the ZIP by matching its PK magic bytes at a raw byte 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 2
    Extract the embedded ZIP archive
    Observation
    I noticed binwalk reported ZIP archive entries at offsets 0x9B3B and 0x9B7C inside flag.png, with a file named secret/flag.png inside the archive, which confirmed the PNG was a polyglot and suggested running unzip directly on it to recover the hidden 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 can often handle polyglot files, but some versions reject the file with 'Can not open file as archive' when the leading bytes look like a PNG rather than a ZIP signature. unzip is more permissive because it specifically seeks to the end-of-central-directory record at the tail of the file, ignoring whatever precedes it. If 7z fails, switch to unzip which is designed to handle exactly this layout.

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

    binwalk -e does extract the ZIP, but it places the carved bytes at _flag.png.extracted/9B3B.zip and further extracts that into _flag.png.extracted/9B7C/, not at a path called secret/. You still need to navigate into the extracted subdirectory tree to find secret/flag.png. The direct unzip approach mirrors the original directory layout (secret/) without the extra offset-named subdirectories.

    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 3
    Navigate and view the flag
    Observation
    I noticed unzip extracted a secret/ directory containing flag.png, matching the ZIP entry names binwalk had listed, which indicated the flag was rendered as visible text inside that inner image and could be read with strings or an image viewer.
    Change to the secret directory and verify the file is a real PNG, then open it. Headless boxes can read the flag with strings or OCR (no GUI needed); on a desktop, any image viewer works.
    bash
    cd secret
    bash
    file flag.png
    bash
    strings flag.png | grep -i pico

    Expected output

    flag.png: PNG image data, 400 x 300, 8-bit/color RGB, non-interlaced
    picoCTF{Hiddinng_An_i...678a337}
    On a desktop you can also open it with any viewer (xdg-open flag.png, eog flag.png, or transfer to your local machine via scp). On WSL or a headless server, strings works if the flag is rendered as literal text in the file; otherwise use tesseract flag.png stdout for OCR.
    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, you can still read image-embedded flags using strings secret/flag.png if the text is stored literally, or convert to text with tesseract secret/flag.png stdout (OCR). If the flag is purely visual, transferring the file to a local machine with scp and opening it there is the most reliable approach.

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...678a337}

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

Key takeaway

Polyglot files exploit the fact that most file parsers read only as far as they need to and stop at the first valid end marker, ignoring trailing bytes. Concatenating a ZIP archive after a PNG IEND chunk produces a file that image viewers render normally while unzip tools extract the hidden payload intact. This technique appears in malware delivery (smuggling executables inside images to bypass content filters) and in digital forensics where investigators use binwalk to surface embedded archives inside firmware dumps, email attachments, and memory images.

Related reading

Want more picoCTF 2023 writeups?

Useful tools for Forensics

Do these first

What to try next