Secret of the Polyglot picoCTF 2024 Solution

Published: April 3, 2024

Description

The Network Operations Center (NOC) of your local institution picked up a suspicious file, they're getting conflicting information on what type of file it is. They've brought you in as an external expert to examine the file. Can you extract all the information from this strange file? Download the suspicious file here.

Polyglot analysis

Download flag2of2-final.pdf locally.

Install pdftotext (poppler-utils) and an OCR tool such as gocr.

bash
wget https://artifacts.picoctf.net/c_titan/9/flag2of2-final.pdf && \
sudo apt install poppler-utils gocr

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 binwalk and other forensics tools useful for polyglot file analysis.
  1. Step 1
    Confirm the polyglot
    Observation
    I noticed the NOC description said tools were giving conflicting information about the file type, which suggested the file might satisfy multiple format parsers simultaneously and that a raw hex dump would reveal both magic signatures at once.
    A quick hex dump shows the file is both PNG and PDF: PNG magic at byte 0, %PDF- further in. See the hex dumps for CTF guide for more.
    bash
    xxd flag2of2-final.pdf | head
    You should see 89 50 4E 47 (PNG signature) at offset 0 and a %PDF- string later in the dump. That tells you both parsers will accept the file.
    What didn't work first

    Tried: Run 'file flag2of2-final.pdf' and trust its single output label to determine what parsers to use.

    The 'file' command reports only the first matching magic signature it finds, so it labels the file as PNG and you miss the embedded PDF entirely. A polyglot satisfies multiple parsers simultaneously, so you must look at the raw hex (xxd) to spot both magic sequences rather than trusting a single-format detection tool.

    Tried: Use 'strings flag2of2-final.pdf' to search for the flag directly without identifying the file format.

    strings prints all printable byte runs but has no knowledge of PDF structure, so it may surface fragments of the %PDF- header or text objects while mixing in PNG chunk metadata noise. You cannot reliably reconstruct a complete structured flag this way; format-aware extractors like pdftotext parse the cross-reference table to pull text in reading order.

  2. Step 2
    Extract the PDF half
    Observation
    I noticed the hex dump showed a %PDF- marker embedded after the PNG signature bytes, which suggested running pdftotext directly on the polyglot file to extract the PDF text layer and recover one half of the flag.
    pdftotext seeks the %PDF- marker and ignores the PNG bytes that come before it, so the embedded PDF reads cleanly. The output holds the second half of the flag.
    bash
    pdftotext flag2of2-final.pdf && cat flag2of2-final.txt

    Expected output

    picoCTF{f1u3n7_1n_pn9_&_pdf_7f9...}
    What didn't work first

    Tried: Open the file directly in a PDF viewer (evince, Adobe Reader) and copy-paste text from the rendered page to get the flag.

    PDF viewers render text visually but their copy-paste pipeline can silently drop characters, reorder ligatures, or substitute encoding-specific glyphs, producing a mangled string that fails flag submission. pdftotext processes the PDF content stream directly and outputs plain text without the rendering layer's substitutions, making it far more reliable for extracting exact strings.

    Tried: Use binwalk to carve the PDF section out of the file before running pdftotext, assuming pdftotext needs a clean PDF with no leading PNG bytes.

    pdftotext scans for the %PDF- header anywhere in the file and follows the xref table backwards from %%EOF, so it handles the embedded PDF correctly without any pre-carving. Running binwalk -e first can corrupt offset calculations in the extracted section and cause pdftotext to fail on the carved output rather than succeed on the original polyglot.

    Learn more

    A polyglot file is a single file that is simultaneously valid in two or more different formats. Because most file parsers only read as much of a file as their format requires, you can construct files where the PDF parser sees a valid PDF and the PNG parser sees a valid PNG, each extracting different content from the same byte stream.

    pdftotext (part of poppler-utils) converts a PDF's text content to a plain text file. PDF parsers locate the %PDF- header anywhere in the file rather than requiring it at byte 0, then walk the cross-reference table (xref) backwards from %%EOF. That is why the embedded PDF extracts cleanly even though PNG bytes come first.

    • PDF files contain %PDF- near the start and end with %%EOF; the parser scans for these markers regardless of what precedes them.
    • PNG files begin with an 8-byte magic signature 89 50 4E 47 0D 0A 1A 0A; the PNG parser reads from byte 0.
    • The polyglot is crafted so neither parser is confused by the other format's data.
  3. Step 3
    Treat it as a PNG
    Observation
    I noticed the PNG magic bytes 89 50 4E 47 appeared at offset 0 of the file, which suggested renaming the file to .png and using an image viewer or OCR to extract the other half of the flag that the PDF parser would not expose.
    The magic bytes also match a PNG. Rename the file with .png and OCR the image to recover the opening characters picoCTF{... . OCR can introduce spurious whitespace and confuse 0/O or l/1, so verify the result against the picoCTF{...} format carefully.
    Learn more

    Because the file is a polyglot, the same byte stream can satisfy the magic-byte checks for more than one format. Renaming the file and opening it with image tooling reveals content that the PDF viewer path does not show directly.

    OCR is enough here because the embedded image exposes a visible fragment of the flag rather than hiding it with steganography or encryption.

  4. Step 4
    Combine halves
    Observation
    I noticed that the PDF extraction produced a suffix beginning partway through the flag format and the PNG OCR produced a prefix starting with picoCTF{, which confirmed that neither parser alone yielded a complete flag and that concatenating the two outputs was required.
    Concatenate the PNG-derived prefix with the PDF-derived suffix to get the full flag picoCTF{f1u3n7_1n_pn9_&_pdf_7f9...}.
    Learn more

    Splitting a secret across two extraction methods is a clever CTF design that tests whether solvers understand that a single file can contain multiple data layers. Neither the image nor the text rendering alone gives the complete flag; you must use both parsers and combine their outputs.

    This mirrors real-world scenarios where malware or hidden data exploits format ambiguity. Security researchers have demonstrated polyglots combining PDF+ZIP, PNG+ZIP, JPEG+HTML, and many other pairings. Some web upload validators can be bypassed this way: a file that passes as an image but also contains active HTML or script content.

    The key insight for all polyglot challenges is to ask: what tool treats this file differently than my first assumption? Trying binwalk, file, strings, and format-specific extractors on every suspicious file is standard forensics methodology.

Interactive tools
  • 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.

Flag

Reveal flag

picoCTF{f1u3n7_1n_pn9_&_pdf_7f9...}

Half PNG + half PDF = full flag.

Key takeaway

Polyglot files exploit the fact that most format parsers only look for their own magic bytes and ignore everything else, so a single byte stream can satisfy two completely different format specifications simultaneously. Security validators that rely on file extension checks or single-parser magic-byte detection are easily fooled by polyglots, which is how attackers bypass upload filters with files that appear to be safe images but also contain valid HTML, JavaScript, or ZIP content. When analyzing suspicious files, always try multiple parsers and tools rather than trusting the first interpretation.

Related reading

Want more picoCTF 2024 writeups?

Tools used in this challenge

What to try next