Skip to main content

Scan Surprise picoCTF 2024 Solution

The flag ships as a QR code rather than text, so locate flag.png and decode it with any QR scanner.

Published: April 3, 2024Updated: August 25, 2026

Description

I've gotten bored of handing out flags as text. Wouldn't it be cool if they were an image instead?

QR decoding

Either download challenge.zip or SSH into atlas and cd ~/drop-in.

Ensure you have zbarimg installed if you want to decode locally.

bash
wget https://artifacts.picoctf.net/c_atlas/3/challenge.zip && \
unzip challenge.zip && \
sudo apt install zbar-tools

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Locate flag.png
    Observation
    The challenge description said the flag was delivered as an image, so finding the actual image file was the necessary first step before any decoding could happen.
    If you SSH'd into atlas, the QR image lives at ~/drop-in/flag.png. If you downloaded challenge.zip and extracted locally, you'll find it inside the unzipped directory at ./challenge/flag.png (the path may be ./flag.png depending on the archive layout - run find . -name 'flag.png' to confirm).
    Learn more

    QR codes (Quick Response codes) are two-dimensional barcodes that encode data using a grid of black and white squares. They were invented in 1994 by Denso Wave for tracking automotive parts and can store URLs, plain text, contact information, or arbitrary binary data up to about 3 KB.

    In CTFs, QR codes are a common steganography-adjacent technique: the flag is hidden in plain sight but requires a specific tool to read. The image is not encrypted - a QR reader recovers the data with no key or password. The "security" is purely through obscurity.

    • QR codes include built-in error correction (up to 30% of the code can be damaged or obscured and still decode correctly).
    • The three large squares in the corners are finder patterns that help scanners locate and orient the code.
    • For forensics challenges, QR codes can also be found embedded in PDFs, inside other images, or even represented as ASCII art.
  2. Step 2Scan the code
    Observation
    The file is flag.png and the challenge is about QR decoding. This calls for a barcode reader such as zbarimg, not a stego or crypto tool.
    Run zbarimg on the file and grep out just the flag in one pipeline. The format prefix from zbarimg (QR-Code:) is stripped by grep -o, leaving picoCTF{...} on stdout.
    bash
    zbarimg flag.png
    bash
    zbarimg flag.png | grep -o 'picoCTF{.*}'

    Expected output

    picoCTF{p33k_@_b00_a81...}
    What didn't work first

    Tried: Running steghide or binwalk on flag.png to look for hidden data inside the image.

    steghide and binwalk look for hidden payloads and embedded archives, not QR content. Nothing is buried in the image bytes; the flag is the pattern itself. zbarimg reads the grid and decodes it.

    Tried: Uploading flag.png to an online QR decoder website instead of decoding locally.

    An online decoder does return the flag, but the third-party service logs every upload. The flag is the secret you are competing for, and sending it to a public site gives it away. Decode locally with zbarimg or pyzbar.

    Learn more

    zbar is an open-source library and command-line suite for reading barcodes and QR codes from images and video streams. zbarimg takes an image file and prints all detected codes to stdout in the format TYPE:data, making it perfect for piping into grep or other tools.

    Alternatives include qrdecode, Python's pyzbar library, and phone cameras (modern iOS and Android detect QR codes natively in the camera viewfinder without any additional app). For CTFs in particular, treat flag images as sensitive: do not upload flag.png to an online QR decoder. The flag is the secret you're trying to keep, and a third-party site logs every input. Decode locally with zbarimg, pyzbar, or your own phone, never via a public web service.

    For offline/CTF use, zbarimg is the most scriptable: you can run it inside a loop over a directory of images, or pipe its output directly to the flag checker, making it efficient when challenges contain multiple QR codes or when you need to process images programmatically.

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.
  • QR Code & Barcode DecoderDecode QR codes, Data Matrix, Aztec, PDF417, and 1D barcodes from any uploaded image. Browser-native, no upload to a server.

Flag

Reveal flag

picoCTF{p33k_@_b00_a81...}

Scanning the QR code reveals the flag instantly.

Key takeaway

A QR code is a machine-readable encoding, not encryption or concealment: any reader recovers the payload with no key at all. The same is true of base64, barcodes, and hex strings. Encoding chosen for convenience offers no confidentiality, because the algorithm is public. Recognizing the signature of an encoding and reaching for its decoder, rather than for cryptanalysis, is basic triage.

Related reading

Tools used in this challenge

Where to go next