Ворота есть... А флаг где? (Font Steganography)
Ворота есть... А флаг где? (Font Steganography)
Platform: hackerlab | Category: Steganography | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2025-12-22 | Status: Solved Techniques: Custom font glyph extraction with fontTools, Font-based steganography detection, ODT file structure analysis (ZIP-based format), SVG path visualization from font glyphs
Summary
Task: ODT file with embedded custom font. Solution: Extract font glyphs using fontTools to reveal hidden message drawn in each glyph.
Ворота есть... А флаг где? — hackerlab.pro
Description
"Ворота есть... А флаг где?.." (Gates are there... But where is the flag?)
Provided file task.zip containing task.odt.
Analysis
1. ODT File Structure
ODT (OpenDocument Text) is a ZIP archive. Extracting:
bash read-only • copy allowedunzip task.odt -d task_extracted/
Structure:
task_extracted/
├── Pictures/
│ └── gates.jpg # Image of gates (red herring)
├── Fonts/
│ └── Font_Myfont_1.ttf # Custom font "Myfont"
├── content.xml # Document content
├── styles.xml
├── meta.xml
└── ...
2. Document Content Analysis
In content.xml found:
- Document contains only one character:
; - Character is rendered with custom font "Myfont"
- Gates image is a distraction (matches the hint "Gates are there")
3. Custom Font Analysis
Font metadata Font_Myfont_1.ttf:
- Name: "Myfont"
- Creation date: 25-01-2023
- Number of glyphs: 66 (A-Z, a-z, punctuation marks)
Key observation: Each glyph contains not a standard letter, but hand-drawn text!
Solution
Extracting Glyphs from Font
python read-only • copy allowed#!/usr/bin/env python3 from fontTools.ttLib import TTFont from fontTools.pens.svgPathPen import SVGPathPen import os font = TTFont('Font_Myfont_1.ttf') glyph_set = font.getGlyphSet() os.makedirs('glyphs', exist_ok=True) for i, glyph_name in enumerate(font.getGlyphOrder()): if glyph_name == '.notdef': continue pen = SVGPathPen(glyph_set) glyph_set[glyph_name].draw(pen) path = pen.getCommands() if not path: continue # Get bounding box for scaling glyph = glyph_set[glyph_name] svg_content = f'''<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -800 1000 1200"> <g transform="scale(1,-1) translate(0,-400)"> <path d="{path}" fill="black"/> </g> </svg>''' with open(f'glyphs/{i:02d}_{glyph_name}.svg', 'w') as f: f.write(svg_content) print(f"Exported: {glyph_name}") print(f"\nTotal glyphs: {len(font.getGlyphOrder())}")
Visualizing All Glyphs
python read-only • copy allowed#!/usr/bin/env python3 """Creating a single image of all glyphs""" from fontTools.ttLib import TTFont from fontTools.pens.svgPathPen import SVGPathPen font = TTFont('Font_Myfont_1.ttf') glyph_set = font.getGlyphSet() glyphs_data = [] for glyph_name in font.getGlyphOrder(): if glyph_name == '.notdef': continue pen = SVGPathPen(glyph_set) glyph_set[glyph_name].draw(pen) path = pen.getCommands() if path: glyphs_data.append((glyph_name, path)) # Create SVG with all glyphs in a row cols = 10 rows = (len(glyphs_data) + cols - 1) // cols cell_width = 150 cell_height = 200 svg = f'''<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="{cols * cell_width}" height="{rows * cell_height}" viewBox="0 0 {cols * cell_width} {rows * cell_height}"> <rect width="100%" height="100%" fill="white"/> ''' for i, (name, path) in enumerate(glyphs_data): col = i % cols row = i // cols x = col * cell_width + 20 y = row * cell_height + 150 svg += f''' <g transform="translate({x},{y}) scale(0.15,-0.15)"> <path d="{path}" fill="black"/> </g> <text x="{col * cell_width + 75}" y="{row * cell_height + 190}" text-anchor="middle" font-size="12">{name}</text> ''' svg += '</svg>' with open('all_glyphs.svg', 'w') as f: f.write(svg) print("Created all_glyphs.svg")
Visualization Result
When viewing all glyphs in their order in the font, they form the text:
Hello!_Here_is_your_flag:CODEBY{REDACTED}
Each font "character" actually contains a hand-drawn letter of the message, not a standard glyph.
Detection Evasion Techniques
The challenge author used:
- Red herring — gates image distracts attention
- Minimal content — only one character
;in the document - Hiding in structure — flag in font glyphs, not in text
Alternative Approaches
- FontForge — GUI tool for viewing font glyphs
- Online font viewers — web services for TTF file analysis
- Manual inspection — install the font and type all characters
Related Techniques
- Steganography in document metadata
- Font substitution attacks
- Homoglyph attacks (visually similar characters)
- Zero-width character steganography