SteganographyFile Steganography
Polyglot Files
steganographyintermediate
Understand and create polyglot files - valid in two formats simultaneously - used in CTF steganography.
steganographypolyglotpng-zippdf-zipfile-formatmagic-bytes
Polyglot Files
A polyglot file is simultaneously valid in two (or more) file formats. CTF challenges use polyglots to hide content — a file looks like a PNG but is also a valid ZIP archive. The trick exploits how different parsers read files: PNG reads front-to-back, ZIP reads back-to-front, so both can coexist in the same bytes.
Common Polyglot Combinations
| Combination | How It Works |
|---|---|
| PNG + ZIP | ZIP's end-of-central-directory can appear after PNG's IEND chunk |
| JPEG + ZIP | ZIP appended after JPEG's FF D9 end marker |
| PDF + ZIP | ZIP structure after PDF's %%EOF |
| GIF + JS | GIF89a/* valid as GIF header + JS comment |
| HTML + ZIP | HTML parsed front-to-back; ZIP parsed end-to-front |
Detecting Polyglots
Check with file and unzip
file suspicious.png # → PNG data
unzip -l suspicious.png # → if shows file listing, it's also a ZIP!Run binwalk to find all embedded formats
binwalk suspicious.png
# DECIMAL HEX DESCRIPTION
# 0 0x0 PNG image
# 12345 0x3039 Zip archive data, "flag.txt"Extract with binwalk or manually
binwalk -e suspicious.png
ls _suspicious.png.extracted/Or manually carve the ZIP:
data = open('suspicious.png','rb').read()
zip_start = data.find(b'PK\x03\x04')
if zip_start != -1:
open('hidden.zip','wb').write(data[zip_start:])
print(f'ZIP found at offset {zip_start}')Format-Specific Notes
# Create PNG+ZIP polyglot:
zip hidden.zip flag.txt
cat innocent.png hidden.zip > polyglot.png
# Verify both work:
file polyglot.png # → PNG data
unzip -l polyglot.png # → shows flag.txt
# Detect and extract:
unzip polyglot.png # directly unzips
binwalk -e polyglot.png # also worksChecklist
-
binwalk suspicious_file→ multiple formats detected? -
unzip -l suspicious_file→ ZIP structure in non-ZIP file? - Python: find
b'PK\x03\x04'(ZIP) orb'\x89PNG'orb'%PDF' -
filecommand: always check true type -
binwalk -e: extract all embedded formats - For PDF:
peepdffor stream analysis - For images: try
unzipdirectly on the file
Last updated on