Polyglot File Generator — Hide Data in Plain Sight
MaskByte crafts a single output file that is simultaneously valid as multiple formats. Every parser only reads the bytes it cares about; everything else hides in plain sight.
Modern security controls — AV engines, WAF rules, file-upload validators, and sandbox analysers — rely on file extension checks, MIME sniffing, and magic-byte inspection to decide whether a file is "safe". MaskByte breaks that assumption by producing one file that satisfies multiple parsers at once.
Bypassing File Upload Restrictions
Many web applications whitelist only "safe" extensions like .mp4, .ico, or .pdf. MaskByte lets you craft a file that satisfies the server's extension/MIME check and hides an embedded ZIP, EXE, DEB, or arbitrary binary payload inside — all in a single upload.
Payload Delivery & AV Evasion Wrap shellcode, reverse shells, or second-stage loaders inside a structurally valid video or image. Slip past:
- Antivirus scanners that inspect only the leading magic bytes
- Content Security Policies that permit media but block executables
- Email gateways that allow attachments below a certain size
WAF & Content Filter Bypass
Embed a fully valid HTML page or PDF inside an .mp4 container. The WAF sees a video file; the browser or PDF reader opens the embedded content.
Red Team Artefact Masking
Package implants, C2 configs, or loaders as .docx, .apk, or .epub files (all valid ZIP containers) while the outer file passes format validation as a legitimate MP4 video.
Format Confusion Attacks Demonstrate parser differential vulnerabilities in file-handling pipelines — a concrete proof-of-concept that a single byte stream can be interpreted differently by different security controls.
CTF Challenges & Steganography Build files that appear as one format to automated scanners but reveal hidden data to a human analyst who knows where to look.
| Layer | Format | Notes |
|---|---|---|
| Always | ICO | Windows icon — valid at byte 0 |
| Always | MP4 | ISO Base Media container |
| Optional | PNG | Embedded in MP4 skip atom |
| Optional | HTML | Web page wrapped in skip atom |
| Optional | Injected as a PDF stream in the ftyp dead space |
|
| Optional | ZIP | Appended with patched central-directory offsets (also JAR, APK, DOCX, XLSX, EPUB, ODF) |
| Optional | TAR | Appended raw (use tar -i to extract) |
| Optional | BIN | Arbitrary binary appended raw |
| Optional | DEB | Debian package appended raw |
| Optional | EXE | Windows PE appended raw |
| Optional | ISO | Raw append (positional argument) |
| Tool | Purpose |
|---|---|
ffmpeg |
Re-encode / generate the MP4 container |
ffprobe |
Detect video vs. audio streams |
mp4edit |
Replace / insert MP4 atoms (place in the same directory as the binary) |
ghostscript (optional) |
Normalise PDF 1.5+ cross-reference streams to plain tables |
# Clone
git clone <repo-url>
cd maskbyte
# Build the CLI binary
go build -o maskbyte .
# Place required tools alongside the binary
cp /path/to/mp4edit .cd frontend
npm install
npm run build # output goes to frontend/dist/maskbyte generate <output> [appendable...] [flags]Flags
| Flag | Short | Description |
|---|---|---|
--image |
-i |
Image to embed as PNG/ICO (PNG, JPEG, GIF, BMP, TIFF, ICO — max 256×256) |
--media |
-m |
Video or audio source (silent 1-second placeholder used if omitted) |
--html |
-H |
HTML file to embed |
--pdf |
-p |
PDF file to embed |
--zip |
-z |
ZIP archive to append (repeatable; also accepts JAR, APK, DOCX, XLSX, EPUB, ODF) |
--tar |
-t |
TAR archive to append (repeatable) |
--bin |
-b |
Binary file to append (repeatable) |
--deb |
-d |
Debian package to append (repeatable) |
--exe |
-x |
Windows PE to append (repeatable) |
--extra |
-e |
Short binary (< 190 bytes) embedded in ftyp header dead space |
--verbose |
-v |
Show ffmpeg / mp4edit output |
--keep-tmp |
Keep intermediate temp files (debug) |
Examples
# Minimal — ICO + MP4 only
maskbyte generate out.mp4
# ICO + MP4 + PNG from an image
maskbyte generate out.mp4 --image icon.png
# Full polyglot: video + icon + webpage + document + archive
maskbyte generate out.mp4 \
--image icon.png \
--media video.mp4 \
--html payload.html \
--pdf report.pdf \
--zip implant.zip
# Merge multiple ZIP archives into one appended archive
maskbyte generate out.mp4 --zip a.zip --zip b.zip
# Append a Windows PE — output is valid MP4 and valid EXE
maskbyte generate out.mp4 --media video.mp4 --exe shell.exe
# Append a raw ISO as a positional argument
maskbyte generate out.mp4 live.isomaskbyte inspect <file> [--atoms]Scans for: ICO, MP4, PNG, JPEG, GIF, BMP, TIFF, WebM, HTML, PDF, ZIP, TAR, RAR, 7Z, GZIP, MP3, WAV, FLAC, OGG, ELF, PE/EXE, DEB.
maskbyte inspect out.mp4
maskbyte inspect out.mp4 --atoms # also prints the MP4 atom treemaskbyte serve [--port 8080] [--static ./frontend/dist]Starts a local web server with:
| Endpoint | Method | Description |
|---|---|---|
/api/generate |
POST |
Generate a polyglot (multipart/form-data) |
/api/inspect |
POST |
Detect formats in an uploaded file |
/api/health |
GET |
Health check |
/ |
GET |
Serves the React UI from --static |
# Default: port 8080, serves frontend/dist/
maskbyte serve
# Custom port
maskbyte serve --port 9000Open http://localhost:8080 in a browser for the graphical interface.
The React + Vite frontend (in frontend/) provides:
- Generate tab — drag-and-drop file inputs for each format category, filename/extension picker, one-click generate and download.
- Inspect tab — drop any file to instantly detect all embedded format signatures.
To develop the frontend against a running server:
# Terminal 1 — backend
maskbyte serve --port 8080
# Terminal 2 — frontend dev server with proxy
cd frontend
VITE_API_BASE=http://localhost:8080 npm run devByte 0 EOF
┌──────────────────────────────────────────────────────────────────┐
│ ICO header (6 B) │ ftyp atom (288 B) │ MP4 atoms │ [PDF] │ [ZIP] │
└──────────────────────────────────────────────────────────────────┘
↑ ICO parser reads here ↑ ZIP EOCD
↑ MP4 parser starts here ↑ PDF startxref
- ICO — The 6-byte ICO header lives at offset 0. The reserved bytes overlap with the MP4 atom size field via a bithack.
- MP4 — An
ftypatom begins at byte 4 (ICO type byte + bithack). A second realftypat byte 256 takes over once byte 3 is zeroed. - PNG / HTML — Carried in a
skipatom that MP4 players silently ignore. - PDF — Injected as a stream object in the 218-byte dead space inside
ftyp. The xref table is patched to account for the prefix offset. - ZIP — Appended after all MP4 data. Central-directory offsets are patched to include the prefix length so unzip tools find the correct entries.
- TAR / BIN / DEB / EXE / ISO — Appended raw; each format's parser seeks to its own magic independently.
Multipart form fields:
| Field | Type | Description |
|---|---|---|
output_name |
string | Desired output filename (e.g. payload.mp4) |
image |
file | PNG/JPEG/GIF/BMP/TIFF/ICO (max 256×256) |
media |
file | Video or audio |
html |
file | HTML page |
pdf |
file | PDF document |
zip |
file | ZIP / JAR / APK / DOCX / XLSX / EPUB / ODF |
tar |
file | TAR archive |
bin |
file | Raw binary |
deb |
file | Debian package |
exe |
file | Windows PE |
iso |
file | ISO image (appended raw) |
Response: binary file download with headers:
Content-Disposition: attachment; filename="..."X-Detected-Formats: ICO,MP4,ZIP,...
Multipart form field file. Returns JSON:
{
"filename": "out.mp4",
"size": 204800,
"formats": [
{ "name": "ICO", "valid": true, "detail": "1 image(s)" },
{ "name": "MP4", "valid": true, "detail": "ftyp at +4, brand=\"isom\"" },
{
"name": "ZIP",
"valid": true,
"detail": "local header +98304, EOCD +200192"
}
]
}maskbyte/
├── main.go # Entry point
├── cmd/
│ ├── root.go # Root cobra command
│ ├── generate.go # `generate` subcommand (CLI)
│ ├── inspect.go # `inspect` subcommand + detectFormats()
│ ├── engine.go # GeneratePolyglot() core logic
│ ├── handlers.go # HTTP handlers for /api/*
│ └── server.go # `serve` subcommand + CORS middleware
├── frontend/
│ ├── src/
│ │ ├── App.jsx # Generate + Inspect pages
│ │ ├── components/ # CategoryCard, FormatBadge
│ │ └── lib/
│ │ ├── api.js # fetch wrappers
│ │ └── categories.js # Format definitions
│ ├── package.json
│ └── vite.config.js
├── mp4edit # Required binary (not included)
├── go.mod
└── go.sum
MaskByte is intended exclusively for authorized penetration testing, CTF competitions, digital watermarking, and IP-protection research. Use against systems you do not own or have explicit written permission to test is illegal and unethical. The authors accept no liability for misuse.