
A font-based deception tool for red teaming, security research, and whatever else.
A font-based deception tool for red teaming, security research, and whatever else.
EvilFontTool hides machine-readable text inside a document that displays completely different text to a human reader. It does this using Evil Fonts — fonts that intentionally deceive the viewer by rendering a different letter than understood by a computer. By remapping font glyphs, the document's visible characters show humans one thing while terminals, AI systems, and clipboard copy paste see another.
The word docx demos do NOT work on mobile due to the way mobile phones render fonts.
pip install evilfonttool
git clone https://github.com/DoctorEww/EvilFontTool.git
cd EvilFontTool
pip install .
For development (editable install):
pip install -e .
Installed automatically via pip:
fonttools — font parsing and manipulationbrotli — WOFF2 compression (used by fonttools)python-docx — DOCX generationreportlab — PDF generationpdf2image — PDF-to-image conversionpdfminer.six — PDF text/layout extractionPillow — image handling for the PDF pipelineSystem requirements (not installed by pip — must be on your PATH):
pdf command, which shells out to soffice --headless to convert DOCX to PDF. The pdf command is experimental on Windows and may not work as intended.
sudo apt install libreofficebrew install --cask libreofficepdf2image to render PDF pages for the pdf command
sudo apt install poppler-utilsbrew install popplerInstall poppler into ~\Documents\poppler and add to path.
irm (irm https://api.github.com/repos/oschwartz10612/poppler-windows/releases/latest).assets[0].browser_download_url -OutFile ~\Documents\poppler.zip
Expand-Archive ~\Documents\poppler.zip ~\Documents\poppler -Force
$bin = (gci ~\Documents\poppler -Recurse -Filter pdftotext.exe)[0].DirectoryName
[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path','User') + ";$bin", 'User'); $env:Path += ";$bin"
/usr/share/fontsC:\Windows\Fontspdf command is experimental on Windows and may not work as intended.doc --ttf-dir <ttffonts_dir> (EvilFontTool embeds them itself) or Word on Windows. LibreOffice's own "embed fonts" option does not work for Evil Fonts.The pdf command doesn't rely on Evil Fonts at all. It renders the DOCX to an image (so the visible page is a picture, not text), then draws the real computer text on top as fully invisible, selectable text. Copy-paste and text extraction read that invisible layer instead. There are a few other tools that can do this, but nothing as easy as the pdf command when you already have a DOCX you like.
If you want a genuine Evil Font PDF, you need to build the Word doc without invisible letters (invisible letters don't survive PDF conversion). From there, export directly from Word or use "Print to PDF." This keeps everything in a single layer, giving the document different IOCs than the well-known two-layer trick used by the pdf command. The pdf command exists purely because that manual process is tedious, and sometimes you just want a quick PDF copy of a Word doc.
TLDR;
If anyone figures out how to pull off Option 2 with invisible letters, I owe you a drink. Open an issue and I'll credit you in the README.
All functionality is exposed via a single CLI with four subcommands.
create — Generate the font family for use in HTML or DOC filesevilfonttool create <reference_font> <output_dir> <font_name>
| Argument | Description |
|---|---|
reference_font | Path to a .ttf or .woff source font |
output_dir | Directory to write fonts and CSS into |
font_name | Internal name prefix for the generated font family |
Example:
evilfonttool create fonts/Arial.ttf output/ 'Arial'
Outputs:
output/fonts/*.woff — web fonts, one per characteroutput/ttffonts/*.ttf — TTF fonts for document embeddingoutput/fonts.css — @font-face declarations for web use.txt files.computer_file must be equal to or longer than the corresponding line in human_fileweb — Generate an Evil Font HTML fileevilfonttool web <human_file> <computer_file> <output_file>
Requires
fonts.cssand the generated fonts to be in the output directory so the HTML file can use it (or change the path in the HTML file).
| Argument | Description |
|---|---|
input_human_file | Text visible to human readers. Can be multiple lines |
input_computer_file | Text visible to machines / AI. Can be multiple lines |
output_file | Path for the generated HTML file |
Example:
evilfonttool web human.txt computer.txt output/index.html
doc — Generate a Evil Font DOCX fileevilfonttool doc <human_file> <computer_file> <output_file> <font_name> [--author AUTHOR] [--ttf-dir DIR]
The
font_namemust match the name used in thecreatestep. The TTF fonts must be installed on the system, embedded via--ttf-dir, or embedded manually in Word (file -> options -> save -> embed fonts) for the deception to render correctly.
Word's own "embed fonts" save option works fine, but LibreOffice's does not -- I could never get it to embed Evil Fonts correctly. Pass --ttf-dir instead: EvilFontTool embeds the fonts itself, directly into the .docx, without relying on Word or LibreOffice's embedding at all.
| Argument | Description |
|---|---|
input_human_file | Text visible to human readers. Can be multiple lines |
input_computer_file | Text visible to machines / AI. Can be multiple lines |
output_file | Path for the generated DOCX file |
font_name | Font family name (must match create step) |
--author | DOCX document author metadata (default: none) |
--ttf-dir | Directory of Evil Font TTFs (e.g. <output_dir>/ttffonts). If given, the fonts actually used are embedded directly into the .docx, so the deception renders correctly without installing them system-wide. Only embeds letters included in the human file. |