Hexter

Dentro de los formatos de archivo binarios: encabezados de PNG, ZIP y Mach-O explicados

Todos los formatos de archivo que usas a diario, imagen, archivo comprimido, ejecutable, tienen una estructura definida hasta el byte, y casi nada de esa estructura es visible a través de las herramientas con las que normalmente abres esos archivos. Vista Previa te muestra una imagen. Utilidad de Archivo te muestra archivos extraídos. Ninguno te muestra los bytes que hicieron posibles esos resultados. Así es como se ven en realidad por debajo tres formatos comunes, y cómo puedes mirarlos tú mismo.

PNG: una secuencia de fragmentos etiquetados

Todos los archivos PNG comienzan con los mismos ocho bytes: 89 50 4E 47 0D 0A 1A 0A. Eso no son datos de imagen, es una firma, elegida deliberadamente para incluir un byte que queda inutilizable si el archivo se transfiere por accidente como texto (0x0A y 0x0D son caracteres de salto de línea, así que una transferencia rota en modo texto los corrompe de una forma fácil de detectar).

Después de la firma, todo en un PNG es un fragmento, y cada fragmento sigue la misma disposición de cuatro partes:

Diagrama de la estructura de un fragmento de PNG: un campo de longitud de 4 bytes, un campo de tipo de 4 bytes como IHDR o IDAT, los datos del fragmento en sí, y una suma de verificación CRC de 4 bytes al final.
Cada fragmento de PNG, desde el primero (IHDR) hasta el último (IEND), sigue esta misma disposición de cuatro campos.
  • Longitud (4 bytes): cuántos bytes de datos siguen, sin contar el tipo ni el CRC.
  • Tipo (4 bytes, siempre ASCII): un código de cuatro letras como IHDR (encabezado de imagen, siempre el primero), IDAT (datos de píxeles comprimidos, puede haber varios) o IEND (marca el final del archivo).
  • Datos: lo que especifique ese tipo de fragmento. Los datos de IHDR son el ancho, la altura, la profundidad de bits y el tipo de color, siempre con la misma disposición fija.
  • CRC (4 bytes): una suma de verificación del tipo y los datos, para que un decodificador pueda detectar un fragmento corrupto en lugar de leerlo mal en silencio.

Ese es todo el formato. Un decodificador de PNG simplemente recorre fragmento tras fragmento, leyendo la longitud para saber cuánto avanzar, hasta que llega a IEND.

ZIP: encabezados locales, luego un directorio al final

Un archivo ZIP almacena cada archivo con su propio encabezado de archivo local, marcado por la firma 50 4B 03 04 (el PK al inicio es una referencia a Phil Katz, el creador del formato). Ese encabezado incluye el nombre del archivo, el método de compresión y tanto el tamaño comprimido como el sin comprimir, seguido inmediatamente por los datos comprimidos del archivo.

La parte que confunde a la gente: esos tamaños y sumas de verificación por archivo en el encabezado local a veces están en cero, con los valores reales almacenados más adelante en un “descriptor de datos”, porque ZIP se diseñó para admitir escrituras en streaming donde el tamaño final no se conoce hasta que los datos ya se han escrito. La lista definitiva de lo que realmente hay en el archivo comprimido vive en un directorio central al final mismo del archivo, que es también la razón por la que algunos ZIP corruptos o truncados pueden parecer que tienen contenido cuando los escaneas desde el inicio, pero no logran abrirse, porque la herramienta que usas lee primero el directorio central y este falta o está dañado.

Mach-O: número mágico, luego comandos de carga

Mach-O es el formato de ejecutable que macOS usa para los binarios compilados. Comienza con un número mágico que le dice a un cargador dos cosas a la vez: si es de 32 o 64 bits, y qué orden de bytes usa el resto del archivo. 0xFEEDFACE es de 32 bits, 0xFEEDFACF es de 64 bits, y si ves los bytes invertidos (0xCEFAEDFE o 0xCFFAEDFE), significa que el archivo se escribió en el orden de bytes opuesto al de la máquina que lo lee.

Después del número mágico viene un encabezado fijo (tipo de CPU, tipo de archivo y un conteo de comandos de carga), seguido de esa cantidad de comandos de carga en secuencia. Los comandos de carga son la forma en que un archivo Mach-O describe todo lo que el cargador necesita: qué segmentos mapear en memoria, qué bibliotecas dinámicas enlazar, dónde está el punto de entrada. Es una idea similar a los fragmentos de PNG: un encabezado fijo, luego una secuencia de registros autodescriptivos, cada uno diciéndole al lector cuánto avanzar para llegar al siguiente.

Mirar esto tú mismo

Nada de esto requiere escribir un analizador. Abre cualquier archivo PNG, ZIP o Mach-O en Hexter y la pestaña Analizar reconoce el formato automáticamente, recorriendo la estructura real de fragmentos o comandos de carga y mostrándola como un árbol junto al hex en bruto, de modo que puedes hacer clic en un campo y ver exactamente de qué bytes provino. Es de solo lectura de forma predeterminada, así que esto es genuinamente seguro de hacer sobre un archivo real, el binario de una app, una captura de pantalla, un archivo comprimido que descargaste, sin riesgo alguno de alterarlo.

Si quieres verificar lo anterior a mano: abre un PNG y comprueba que los primeros ocho bytes coincidan con la firma, luego mira los bytes 8 al 11 (la longitud del primer fragmento) y los bytes 12 al 15 (su tipo, que debería leerse IHDR). Es un ejercicio lo bastante pequeño como para hacerlo en un par de minutos, y es una forma genuinamente útil de entender un formato de archivo que has usado toda tu vida pero que nunca miraste de verdad.