Description
A seemingly harmless "Country Flags" gallery hides a covert message from the Upanzi Network. Inspect the list of flags, identify the odd entry, and extract the hidden data from its PNG.
Spin up the challenge instance and browse the provided gallery URL.
Pull the page source with curl, then grep it for flags/ references to enumerate every linked image and spot the odd one.
Download the suspicious PNG and confirm it's a real image with file before running stego decoders.
curl http://standard-pizzas.picoctf.net:56409/ -o index.htmlgrep -oE 'flags/[a-zA-Z]+\.png' index.html | sort -uwget http://standard-pizzas.picoctf.net:56409/flags/upz.pngfile upz.pngSolution
Walk me through it- Step 1Spot the rogue flagGrep the page source for every
flags/<name>.pngreference. The output is mostly country codes -usa.png,fra.png,jpn.png, etc. - and one outlierupz.png. Upanzi is a fictional CyLab Africa nation, so its image is the embedded clue. Download it and run a stego decoder.bashgrep -oE 'flags/[a-zA-Z]+\.png' index.html | sort -ubash# Output mostly country codes; upz.png stands out.bashwget http://standard-pizzas.picoctf.net:56409/flags/upz.pngbashfile upz.pngbash# Should report: PNG image data, NNNxNNN, 8-bit/color RGBA, non-interlacedLearn more
OSINT (Open Source Intelligence) and visual reconnaissance are important first steps in CTF challenges. When presented with a list of items, security researchers learn to look for anomalies - entries that don't belong, slightly misspelled names, unusual ordering, or references to fictional entities. "Upanzi" is a fictional African nation referenced in cybersecurity educational contexts, making it immediately suspicious in a list of real countries.
Viewing page source is a fundamental web security technique. HTML comments, hidden form fields, unusual script tags, metadata, and data attributes often contain information that is not visible in the rendered page. Developers sometimes leave debug information, internal API endpoints, or - as in this challenge - clues to hidden functionality directly in the source code.
The gallery structure is a common steganography delivery mechanism: embed a secret-carrying image among many innocuous images so that a casual observer sees only a normal image gallery. Finding the odd one out requires enumeration, which is why tools like
curlcombined with text search (grep) are useful for quickly scanning all entries programmatically rather than reading them visually. - Step 2Install StepicStepic is the Python LSB stego library the challenge name riffs on. Create a virtualenv and
pip install stepic(Pillow comes in as a dependency, so you don't need to install it separately). If install fails, fall back tozsteg upz.png.pythonpython3 -m venv venv && source venv/bin/activatebashpip install stepic # pulls in Pillow automaticallyLearn more
LSB steganography (Least Significant Bit) hides data by replacing the lowest-order bit of each color channel in every pixel with bits from the secret message. The change is visually imperceptible because flipping the LSB changes a pixel's color value by only 1 out of 255. A red pixel at value 200 (11001000) becomes 201 (11001001) - completely indistinguishable to the human eye.
Stepic is a Python library that encodes and decodes messages hidden in PNG images using LSB steganography. The
-dflag (decode) reads the LSB of each channel pixel by pixel, reconstructs the binary stream, and interprets it as text. Note: Stepic encodes into the alpha channel when present, so an RGBA PNG can carry payload bits that an RGB-only decoder will miss entirely. zsteg's bit-plane brute force handles both. It is a straightforward implementation that does not use passwords or additional encoding, making it easy to use but also easy to detect with forensic tools.Other popular LSB stego tools include zsteg (Ruby, scans multiple bit planes and color channel combinations), StegSolve (Java GUI tool that visualizes individual bit planes), and steghide (supports password-protected embedding in JPEG and BMP files). When a challenge does not specify which tool was used, zsteg is often the best first choice because it automatically tries many configurations.
- Step 3Decode the PNGRun Stepic in decode mode against upz.png. It walks each pixel's low bits and prints the embedded ASCII flag. If the default zsteg fallback finds nothing, brute-force bit depths with
zsteg -b. For paranoia,stegoVeritas upz.png --allruns statistical tests to confirm LSB embedding before you keep digging.bashstepic -d -i upz.pngbash# Fallback if Stepic isn't installed:bashzsteg upz.pngbash# zsteg tries multiple bit planes and encodings; if default misses, brute-force:bashzsteg upz.png -b 1,2,3,4Learn more
The PNG format is particularly well-suited for steganography because it uses lossless compression. JPEG images use lossy compression, which discards fine-grained pixel differences during encoding - destroying LSB-embedded data in the process. PNG preserves every pixel value exactly, so LSB payloads survive saving and sharing. This is why most LSB steganography challenges use PNG or BMP files.
Detecting LSB steganography statistically is possible through histogram analysis: LSB embedding creates subtle patterns in the distribution of pixel values that deviate from natural images. Tools like StegoVeritas and academic tools like StegExpose perform these statistical tests to detect the presence of hidden data without knowing the message content. In practice, simple single-bit LSB embedding is easily detected; more sophisticated algorithms like F5 and JPEG steganography with perceptual modeling are harder to detect.
This challenge is a great introduction to the broader field of digital watermarking and information hiding, which has legitimate applications in copyright protection, covert communications research, and digital forensics (detecting when images have been modified or contain hidden content).
Flag
picoCTF{fl4g_h45_fl4ga66...}
Any other LSB steganography decoder (zsteg, StegSolve, etc.) works too; the payload is short plaintext.