Skip to main content

advanced-potion-making picoMini by redpwn Solution

A corrupted image file conceals a flag. Repair the file and look closer at its pixel data.

Published: April 2, 2026Updated: August 13, 2026

Description

Ron just found his own copy of advanced potion making, but it's been corrupted. Help him recover it!

Download advanced-potion-making from the challenge page.

Install a hex editor (e.g. hexedit, ghex, or use xxd) and StegSolve.

bash
xxd advanced-potion-making | head

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
The Introduction to Steganography Tools covers the forensics tools useful for this challenge and explains when to use each one.
  1. Step 1Identify the file type
    Observation
    The file has no extension and file reports it as data rather than a known format, which means the magic bytes at the front are wrong. Dump the raw bytes and find out what the body actually is.
    Run xxd on the file and compare the first 8 bytes to the PNG magic signature 89 50 4E 47 0D 0A 1A 0A. The file contains IHDR and IEND chunks confirming it is a PNG, but the magic bytes at offset 0 are wrong.
    bash
    xxd advanced-potion-making | head
    bash
    file advanced-potion-making

    Expected output

    advanced-potion-making: data
    What didn't work first

    Tried: Trust the 'file' command output alone and conclude the download is corrupted beyond repair.

    file classifies from the first few bytes alone, so a wrong signature gets you 'data' even when everything after it is intact. Scan further into a hex dump and the IHDR and IEND chunk names settle it: the body is a valid PNG and only the header needs fixing.

    Tried: Run strings on the file hoping to find the flag directly without repairing it first.

    strings pulls printable sequences out of raw bytes, and an LSB payload lives in pixel bit planes rather than as printable text, so it finds nothing. It also skips the repair the file actually needs, since viewers and stego tools refuse to touch a broken header.

    Learn more

    Magic bytes (also called file signatures) are fixed byte sequences at the beginning of a file that identify its format. The PNG signature is 89 50 4E 47 0D 0A 1A 0A: the 89 is a non-ASCII byte that prevents the file from being misidentified as text; 50 4E 47 is ASCII "PNG"; the carriage return and line feed sequence detects line-ending corruption; and 1A is a DOS EOF marker. Together they form a robust format fingerprint.

    The file command reads magic bytes rather than file extensions to identify types - this is why file correctly identifies a JPEG renamed to .txt. When magic bytes are corrupted, file reports data (unrecognized binary). Comparing xxd output to published format specifications lets you pinpoint which bytes are wrong.

    PNG chunks provide a secondary confirmation: IHDR (image header) and IEND (image end) are mandatory chunks with fixed names. Finding them in the xxd output confirms the file body is a valid PNG even when the header is corrupted, narrowing the repair to just the first 8 bytes.

  2. Step 2Fix the PNG magic bytes
    Observation
    The dump shows IHDR and IEND chunk names intact, so only the first eight bytes are wrong. Patch the PNG signature in place with dd and the file parses again, with the image data untouched.
    Overwrite the first 8 bytes with the correct PNG signature using dd. The conv=notrunc flag ensures the rest of the file is not truncated.
    bash
    printf '\x89\x50\x4e\x47\x0d\x0a\x1a\x0a' | dd of=advanced-potion-making bs=1 count=8 conv=notrunc
    bash
    file advanced-potion-making
    What didn't work first

    Tried: Use 'dd' without conv=notrunc to write the magic bytes.

    Without conv=notrunc, dd truncates the output to the size of its input, so writing eight bytes deletes everything after them and takes the image with it. You end up with a valid header on an empty file. That option writes in place and leaves the rest alone.

    Tried: Open the file in a hex editor and manually type the PNG signature bytes as ASCII characters 89504E47.

    Typing the hex digits into a text-mode editor writes their ASCII code points, not the byte values they name. The PNG signature needs the raw bytes. Use printf with hex escapes, or a real hex editor in overwrite mode.

    Learn more

    dd is the Unix low-level copy utility. bs=1 sets a block size of 1 byte so it writes exactly as many bytes as specified. count=8 limits it to 8 bytes. Crucially, conv=notrunc prevents dd from truncating the output file to the size of the input - without this flag, the 8-byte write would delete everything after byte 8.

    printf with \\xNN escape sequences emits raw bytes. This is the standard shell idiom for writing arbitrary binary data without a dedicated hex editor. An alternative is Python: python3 -c "import sys; sys.stdout.buffer.write(bytes([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a]))".

    This repair technique - patching just the damaged bytes in-place - is safer than recreating the file because it preserves every byte of the original. The same approach is used in file carving during forensic recovery: extract the known-good body and prepend or repair the header to make the file parseable again.

  3. Step 3Open the repaired image
    Observation
    file now reports a valid 500x500 RGB PNG. Look at it before choosing an extraction technique.
    The file now opens as a solid red PNG image. The flag is hidden in the least-significant bits of the red channel - not visible to the naked eye.
    bash
    eog advanced-potion-making
    What didn't work first

    Tried: Run steghide on the repaired PNG to extract the hidden data.

    steghide uses its own graph-based embedding and requires a passphrase in both directions. This is plain LSB with no passphrase, so it either prompts and fails or reports nothing found. Use a tool that reads bit planes directly.

    Tried: Run zsteg on the image and assume the first result is the flag without checking the channel.

    zsteg walks several channels and bit depths and can surface false positives before it reaches the one you want. Take the first candidate without checking its label and you get garbage. Look for the result on the red channel at bit depth 1.

    Learn more

    LSB (Least Significant Bit) steganography hides data by replacing the lowest-order bit of each pixel's color channel with one bit of the secret message. For an 8-bit red channel, changing bit 0 from 0 to 1 shifts the color by 1/255 - imperceptible to human vision but readable by software that extracts those bits and reassembles them into bytes.

    A solid color image is an ideal steganography carrier for a CTF because the contrast between the data-carrying pixels and the rest is zero to the human eye - every pixel appears to be exactly the same shade of red. Any variation is in the LSB, which the eye cannot distinguish. A photographic image would be a more typical real-world carrier because the natural noise in photos provides cover for the introduced bit-flips.

    The specific focus on the red channel (rather than all channels or a different channel) is a challenge design choice. Tools like StegSolve let you isolate individual color planes and bit depths to find where hidden data lives, rather than having to check all 24 possible bit planes manually.

  4. Step 4Extract the hidden flag with StegSolve
    Observation
    The repaired image is a uniform solid red with no visible variation, which is the classic LSB carrier. Inspect the red channel's lowest bit plane, where the hidden data reads as structure rather than noise.
    Open the repaired file in StegSolve. Navigate to the Red plane 0 view. The flag text becomes clearly readable in the LSBs of the red channel.
    Learn more

    StegSolve is a Java application for image steganography analysis. Its "Bit Plane" view renders each bit of each color channel as a separate black-and-white image - white pixels where the bit is 1, black where it is 0. Plane 0 is the LSB plane. If the LSBs are not random noise but instead encode structured data (like ASCII text), the pattern will be immediately visible as text or a recognizable image.

    The workflow - view each plane, look for patterns, extract data - mirrors what automated steganography detection tools do. Tools like zsteg (for PNG and BMP), steghide (password-protected hiding), and outguess each use different embedding algorithms. When a stego challenge does not specify the tool used, you try common ones in sequence.

    Steganography differs from encryption: encryption hides the content of a message while its existence is known, whereas steganography hides the existence of the message entirely. In practice they complement each other - encrypt the message, then hide it steganographically, so an adversary who finds the carrier file still cannot read the content.

Interactive tools
  • 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.
  • File Magic IdentifierIdentify file types from magic numbers. Paste hex bytes or drop a file to detect PNG, JPEG, ZIP, PDF, ELF, PCAP, SQLite, and dozens of other formats.
  • 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{w1z4rdry}

PNG files have a fixed 8-byte magic signature - corrupting just these bytes makes the file unreadable to any image viewer despite all image data being completely intact.

Key takeaway

Every binary format opens with a magic sequence that parsers check before reading anything else. Corrupt those bytes and tools report the whole file as unrecognized while everything after them is fine, which makes a surgical in-place patch the right repair. LSB steganography works because the lowest bit of a pixel value contributes almost nothing to the color you see, so replacing those bits carries arbitrary data with no visible change.

Related reading

Useful tools for Forensics

Where to go next