Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
z80-sans — Fuente OpenType que desensambla instrucciones Z80 | Kitploit
Herramientas/GitHubGitHub/nevesnunes/z80-sans
Ingeniería InversaFuzzingCTFSeguridad de HardwareAnálisis de BinariosAprendizaje y Educación
GitHubnevesnunes/z80-sans

z80-sans

Fuente OpenType que desensambla instrucciones Z80

Ver Repositorio
5063hace 1 añoRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Z80 Sans

¿Cuál es tu desensamblador favorito? El mío es una fuente:

https://github.com/user-attachments/assets/bb6ceb18-c2fd-40a9-be4f-202321a214d9

Esta fuente convierte secuencias de caracteres hexadecimales en minúsculas en instrucciones Z80 desensambladas, haciendo un uso extensivo de la Tabla de Sustitución de Glifos (GSUB) y la Tabla de Posicionamiento de Glifos (GPOS) de OpenType.

Si solo quieres probarla, hay una copia disponible en ./test/z80-sans.ttf.

Instalación

Probado en Debian GNU/Linux 12. Ten en cuenta que esta versión de Debian incluye ruby versión 3, mientras que fontcustom fue escrito para ruby versión 2 y es incompatible con versiones posteriores (por ejemplo, errores de sintaxis). Una instalación de ruby también requiere una versión compatible de OpenSSL. Por lo tanto, se puede usar RVM para gestionar tanto ruby como una instalación local de OpenSSL.

root@kitploit:~
apt install imagemagick potrace
pip install fonttools

git submodule update --init --recursive

# fontforge
(
cd ./modules/fontforge/
git checkout 4f4907d9541857b135bd0b361099e778325b4e28
git apply ../../resources/fontforge.diff
mkdir -p build
cd build
cmake -GNinja ..
ninja
ninja install
)

# woff2
(
cd ./modules/woff2/
make clean all
)

# fontcustom
rvm use 2.7
rvm pkg install openssl
rvm install 2.4 --with-openssl-dir=$HOME/.rvm/usr
gem update --system 3.3.22
(
export PATH=$PWD/modules/woff2/build:$PATH
cd ./modules/fontcustom/
git apply ../../resources/fontcustom.diff
gem build fontcustom.gemspec
gem install ./fontcustom-2.0.0.gem
)

Ejecución

root@kitploit:~
cp ./resources/droid-sans-mono.ttf /tmp/base.ttf
./gen.py ./resources/instructions.json

El archivo de fuente .ttf se copia a ~/.local/share/fonts/, que es usado por ejemplo por LibreOffice.

Diseño

En comparación con otras fuentes malditas, Z80 Sans tiene estos desafíos:

  • Múltiples caracteres para renderizar: sería poco práctico definir manualmente carácter por carácter todas las reglas de sustitución para el renderizado, por lo que podemos crear glifos que combinen múltiples literales (por ejemplo, mnemónicos como CALL), sin embargo esto también está ligado al siguiente punto...
  • Múltiples combinaciones: recuerda que algunas instrucciones Z80 pueden tomar direcciones de 16 bits y registros como operandos, lo que significa que una sola instrucción puede tener hasta 65536 * 7 = 458752 combinaciones posibles.
  • Operandos fuera de orden: por ejemplo, los registros y desplazamientos pueden codificarse en bytes hexadecimales en un orden, pero desensamblarse en otro orden, lo que complica las reglas de retroceso/anticipación.
  • Direcciones little-endian: los caracteres del byte menos significativo deben renderizarse antes que el byte más significativo.
  • Desplazamientos con signo: todos los desplazamientos en el rango 0x80..0xff deben renderizarse como un número negativo en complemento a dos.

Todo esto requiere una solución programática. Mientras que fontcustom e ImageMagick se encargan de generar glifos, parece que una forma conveniente de escribir reglas de búsqueda es el formato .fea, pero no encontré una manera de integrarlo con el formato .ttx de fonttools (que es básicamente xml). Tomé el enfoque del mínimo común denominador editando directamente el .ttx de Noto Sans Mono (aunque las formas de los glifos se calculan a partir de Droid Sans Mono, ya que fue con lo que empecé al parchar FontForge).

Se utiliza un analizador de descenso recursivo para generar todos los glifos posibles, lo que ayuda a evaluar expresiones en codificaciones (por ejemplo, SET b,(IX+o) toma un bit y un desplazamiento, codificado como la expresión DD CB o C6+8*b). Luego, estas codificaciones se expandieron a todos los valores posibles que pueden tomar los operandos, antes de asociar finalmente 1 o más bytes hexadecimales a cada glifo de desensamblado necesario para renderizar una instrucción expandida.

Hay algunas buenas referencias sobre las características de OpenType, pero están escritas a un nivel alto, o en formato .fea(?):

  • OpenType Feature File Specification | afdko
  • GSUB — Glyph Substitution Table (OpenType 1.9.1) - Typography | Microsoft Learn
  • Fonts and Layout for Global Scripts
  • GitHub - brew/opentype-feature-intro: An introduction to OpenType features for type designers.
  • Features, part 3: advanced contextual alternates | Glyphs
  • Opentype subtitution many by many (different number) - Glyphs Forum

Nunca está muy claro cómo traducirlas a .ttx, así que al final simplemente convertí toda la familia Noto Sans y usé el viejo y confiable enfoque de "aprender con el ejemplo". Esto es incluso más divertido de lo que parece, gracias a los numerosos fallos silenciosos al convertir de .ttx a .ttf, donde las búsquedas no coinciden debido a algunas suposiciones no validadas por fonttools (por ejemplo, las definiciones de clase para sustituciones de encadenamiento contextual deben tener al menos un glifo de cobertura con valor de clase="1").

Prácticamente todos los desafíos se resolvieron con reglas de encadenamiento contextual. Para manejar direcciones, cada nibble en el rango 0..f se codificó con glifos distintos, utilizando caracteres espaciadores para crear múltiples sustituciones, un carácter a la vez. Los desplazamientos también tienen variantes con signo adicionales. Esto nos da un total de (4 + 2) * 16 glifos para números. Esto ya fue suficiente para mantener el archivo de fuente por debajo del límite de 65536 glifos.

La peor parte fueron, por supuesto, los operandos fuera de orden. Sin embargo, debido al número limitado de variaciones que estos tienen en las instrucciones, se pudieron cubrir con la misma estrategia que las instrucciones con prefijos codificados de manera ambigua, por ejemplo:

root@kitploit:~
["SET b,(IX+o)", "DD CB o C6+8*b"],
["SET b,(IY+o)", "FD CB o C6+8*b"],

Se cubre con las mismas reglas de búsqueda que:

root@kitploit:~
["SRA (IX+o)", "DD CB o 2E"],
["SRA (IY+o)", "FD CB o 2E"],
["SRL (IX+o)", "DD CB o 3E"],
["SRL (IY+o)", "FD CB o 3E"],

Una propiedad interesante en el ISA Z80 es que los bits y los registros tienen hasta 8 variaciones, y estos casos fuera de orden solo involucran desplazamientos y uno de esos operandos específicos. Por lo tanto, podemos codificar bits o registros como literales. Con suficiente anticipación, podemos coincidir hasta el último byte hexadecimal y crear búsquedas dedicadas para cada caso. Los últimos literales se pueden reducir generando una ligadura que coincida con el glifo del sufijo. El resultado final fueron docenas de búsquedas generadas adicionales para estos casos (que probablemente se puedan agrupar para reducir este número).

Problemas conocidos

  • Aunque todo el conjunto de instrucciones original debería desensamblarse, algunas instrucciones tienen pequeños fallos:
    • LD (IX+o),r se renderiza como LD (IX+o r),;
    • SET b,(IX+o) se renderiza como SET b,(IX+o));
  • Código de "calidad CTF" 😅;

Trabajo futuro

FontForge admite la modificación programática de características mediante los comandos GenerateFeatureFile() y MergeFeature() (brevemente cubierto en The Terrible Secret of OpenType Glyph Substitution - Ansuz - mskala's home page). Solo me enteré de esto después de hacer la implementación basada en .ttx, pero podría haber evitado tener que tocar los archivos .ttx.

Para conjuntos de instrucciones más complejos, un enfoque alternativo que parece tener menos restricciones es usar moldeadores de fuentes. Algunos ejemplos:

  • fuglede/llama.ttf: A font for writing tiny stories;
  • hsfzxjy/handwriter.ttf: Handwriting synthesis with Harfbuzz WASM.;

Créditos

  • Droid Sans Mono y Noto Sans Mono se usaron como base para Z80 Sans.
  • ./resources/instructions.json fue adaptado de maziac/z80-instruction-set.
  • Inspiración para las sustituciones GSUB:
    • Font with Built-In Syntax Highlighting;
    • Fontemon, en particular "How I did it";
    • Addition Font;
    • Sans Bullshit Sans;

Licencia

  • Droid Sans Mono está bajo Licencia Apache;
  • Noto Sans Mono está bajo Open Font License;
  • ./resources/instructions.json está bajo GNU Lesser General Public License versión 3;
  • Otros archivos están bajo Licencia MIT;
Descargar herramienta