Browse CTFs New CTF Sign in

Hidden ZIP in image

forensic_file_artifacts Difficulty 1–5 30 min certifiable

Theory

Why This Matters

Polyglot files — binary files that are simultaneously valid in two or more formats — have appeared in real-world malware campaigns and data-exfiltration incidents. Security researchers have documented PDF/ZIP and JPEG/ZIP polyglots used to bypass file-type filters on email gateways and upload validators. In digital forensics casework, investigators routinely discover that suspects concealed documents or evidence by appending a ZIP archive to the end of a JPEG, exploiting the fact that image viewers parse from the beginning of the file while ZIP parsers read the central directory from the end. Recognising this pattern quickly determines whether a seized image is purely photographic evidence or a container carrying additional criminal material.

Core Concept

A JPEG file is parsed front-to-back: the decoder reads a SOI marker (0xFF 0xD8), processes a sequence of marker segments, and stops at the EOI marker (0xFF 0xD9). Any bytes that follow the EOI are entirely ignored by standard image viewers. A ZIP archive is parsed back-to-front: the parser searches for the End of Central Directory (EOCD) record (PKx05x06, i.e., 0x50 0x4B 0x05 0x06) near the end of the file, reads the offset to the Central Directory, and from there locates each Local File Header (LFH) marked PKx03x04 (0x50 0x4B 0x03 0x04). Because these two parsers use opposite ends of the file as anchors, a single file can satisfy both: the JPEG portion occupies the front, and the ZIP portion (starting at some offset after the JPEG EOI) satisfies the ZIP parser because the EOCD still points to a valid central directory regardless of what precedes it.

The attacker or challenge designer constructs the polyglot by concatenating the JPEG bytes with a well-formed ZIP archive: cat image.jpg archive.zip > challenge.jpg. The file utility on many Linux distributions will report only JPEG image data because it tests the leading magic bytes; the ZIP content is not detected unless entropy or signature scanning is applied to the full byte stream. This is the trust boundary violation: content-inspection tools that only check the file header fail to detect the embedded secondary format.

File carving is the process of recovering files from a raw byte stream without relying on filesystem metadata, using only known magic byte signatures (file headers and footers) to identify and extract file boundaries. In the polyglot scenario, carving means locating the PKx03x04 signature at a non-zero offset and extracting everything from that point to the end of the file (or to the EOCD record).

Technical Deep-Dive

# Step 1: Quick type check — will likely show only JPEG
file challenge.jpg

# Step 2: Entropy scan and signature detection with binwalk
binwalk challenge.jpg
# Expected output for a JPEG+ZIP polyglot:
# DECIMAL       HEXADECIMAL     DESCRIPTION
# 0             0x0             JPEG image data, JFIF standard 1.01
# 152389        0x252C5         Zip archive data, at least v2.0 to extract,
#                               compressed size: 341, name: secret.txt
# 153014        0x25536         End of Zip archive, footer length: 22

# Step 3: Carve with binwalk (auto-extract all detected signatures)
binwalk -e --dd='.*' challenge.jpg
# Extracted files appear in _challenge.jpg.extracted/

# Step 4: Manual carve with dd (if binwalk is unavailable)
# Find the ZIP LFH offset from binwalk output: 0x252C5 = 152261 decimal
dd if=challenge.jpg bs=1 skip=152261 of=carved.zip
file carved.zip       # should now report: Zip archive data

# Step 5: Inspect and extract the ZIP
7z l carved.zip       # list contents
7z x carved.zip       # extract

# Step 6: Verify JPEG is still valid after polyglot construction
xxd challenge.jpg | grep -m1 'ffd9'   # EOI should appear before the PK sig
# Partial hex dump around the ZIP header embedded at offset 0x252C5
# Each row = 16 bytes
000252C0: 6f77 6e65 7220 6a70 6567 5048 0304 1400  owner jpegPK....
000252D0: 0000 0800 2b4e 5556 XXXX XXXX XXXX XXXX  ....+NUV........
#                             ^^^^ ^^^^ = CRC-32 of compressed data
# PKx03x04 at offset 0x252C5 is the LFH magic — ZIP starts here

Analytical Methodology

  1. File command baseline — Run file challenge.jpg to record the reported type. If only JPEG is shown, a hidden archive may still exist.
  2. Binwalk signature scanbinwalk challenge.jpg performs an exhaustive search for dozens of known magic-byte signatures throughout the full file, not just the header. Note all offsets reported.
  3. Entropy analysisbinwalk -E challenge.jpg plots per-block entropy. Compressed data (ZIP deflate) has entropy near 1.0; JPEG data also has high entropy, but a flat plateau followed by a sudden boundary may indicate a transition between formats.
  4. Hex inspection of key offsets — Use xxd challenge.jpg | grep -n "504b" to locate all occurrences of the PK signature (hex 50 4B). The first match after the JPEG EOI (FF D9) is the ZIP LFH.
  5. Carve and verify — Carve from the identified offset to end-of-file with dd or binwalk -e, then verify the output with file and attempt listing/extraction with 7z l.
  6. Check for password protection7z l carved.zip reports [protected] on encrypted entries. Note the encryption flag in the LFH (general purpose bit flag bit 0 = 1 for encrypted).
  7. Distinguish benign from suspicious — JPEG files from cameras do not have trailing data after the EOI. Any bytes after FF D9 in a "photo" warrant investigation. Tools like identify -verbose (ImageMagick) will warn about trailing data.

Common Analytical Errors

  • Trusting file alone — The file command reads only the leading magic bytes by default. It will call a JPEG+ZIP polyglot a JPEG. Always follow with binwalk.
  • Missing multi-level nesting — The extracted ZIP may itself contain another embedded archive or a steganographic image. Each extracted file should be re-triaged from the beginning.
  • Off-by-one on the carve offset — If the dd skip value is off by even one byte, the resulting file will have a corrupt LFH and 7z will report an error. Verify the offset in hex first.
  • Ignoring non-ZIP polyglots — The same technique applies to PDF, RAR, 7z, tar.gz, and even ELF binaries appended to images. Do not limit scanning to ZIP signatures.
  • Not checking for a password — A polyglot challenge at increased difficulty will often password-protect the embedded ZIP. Finding the archive is only half the task; the password may be encoded in the image metadata or the filename.
  • Binwalk false positives — Binwalk occasionally reports partial signature matches inside random JPEG data. Confirm with xxd that the suspected offset truly begins with 50 4B 03 04 followed by a plausible version-needed field.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0118 Knowledge of file format structures and common embedded data techniques Teaches JPEG marker structure, ZIP central-directory parsing, and the polyglot construction mechanism
S0065 Skill in identifying and extracting data of forensic interest from file artifacts Practises signature scanning, entropy analysis, and manual file carving with dd and binwalk
S0068 Skill in using binary analysis tools to examine file content Develops proficiency with binwalk, xxd, 7z, and dd for raw binary inspection
T0075 Task: Analyse forensic images to recover data Directly exercises recovery of a hidden archive from a binary image stream

Further Reading

  • The Art of File Carving — Simson Garfinkel, IEEE Security & Privacy
  • Binwalk Documentation and Entropy Analysis Guide — Craig Heffner (ReFirmLabs)
  • Polyglot Files: A Hacker's Guide to Hiding Data — PortSwigger Research Blog
  • File System Forensic Analysis — Brian Carrier (Addison-Wesley)

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.