ZIP in Disguise: Reading File Magic Bytes Instead of the Extension
The challenge
An incident responder pulled report.pdf off a suspect's laptop, but it never opens in a PDF reader. Open it in the hex viewer, compare the first bytes to the reference signatures, and type the real container format.
What you'll learn
- Read the first bytes of a file in a hex viewer and recognise a known file signature
- Match the 50 4B 03 04 'PK' signature to the ZIP container family
- Explain why a file extension is metadata and the magic bytes are ground truth
- Recognise that Office documents and APKs are ZIP containers underneath
- Rule out PDF, RAR, and 7-Zip by comparing their distinct leading signatures
Skills tested
Prerequisites
- Comfort reading hexadecimal byte values
- Awareness that a file extension can be changed freely without altering the contents
How it works
Every common file format begins with a fixed sequence of bytes called a magic number or signature. The operating system and most viewers, however, decide which application to launch based on the file extension - a piece of metadata in the name that any user can rename in a second. That gap is what this challenge exploits: a file called report.pdf whose actual contents are not a PDF at all.
A genuine PDF starts with the ASCII bytes 25 50 44 46, which spell %PDF. The file in front of you instead starts with 50 4B 03 04. The first two bytes, 50 4B, are ASCII PK - the initials of Phil Katz, who created the ZIP format - and 03 04 is the local file header marker. That four-byte sequence is the unmistakable signature of a ZIP archive.
This matters far beyond renamed files. Modern Office documents (.docx, .xlsx, .pptx), Java JARs, and Android APKs are all ZIP containers wearing a different extension. A defender who trusts the extension will mis-triage all of them. The reliable move is always the same: open the header and read the magic bytes.
Common mistakes
- Trusting the extension. Assuming
report.pdfis a PDF because the name says so. The name is metadata; the bytes are the file. - Misreading 50 4B as 'PK was unreadable'. Skipping the ASCII gutter where
50 4Bclearly renders asPK, the giveaway for the ZIP family. - Confusing ZIP with RAR or 7-Zip. RAR begins
52 61 72 21('Rar!') and 7-Zip begins37 7A BC AF; only50 4B 03 04is ZIP. - Stopping at 'it is an archive'. The prompt asks for the specific container format, and the signature names exactly one: ZIP.
How to defend against it
Detection and triage must key on content, not file names, and uploads must be validated by their real type before being stored or processed.
- Use a content-based identifier (a libmagic-style check) on every uploaded or quarantined file rather than its extension.
- For an upload allow-list, verify the magic bytes match the claimed type and reject mismatches, since ZIP-in-PDF is a classic smuggling trick.
- Treat any ZIP-family signature (
50 4B 03 04) carrying a non-archive extension as suspicious and route it for deeper inspection. - When unzipping unknown archives, do so in a sandbox and guard against path traversal (Zip Slip) inside the entries.