Saltar al contenido
Lectura9 minPreview

Firmas, xxd, grep y dd

Casi todos los formatos empiezan con unos bytes fijos, la firma o magic bytes. Windows se fía de la extensión; usted no. Lo primero que corro ante un archivo raro es file, que identifica el tipo por esas firmas y no por el nombre. Para recortar alcanza con saber dónde empieza cada formato y, si se puede, dónde termina.

Las firmas que más va a ver

TipoEmpieza con (hex)Termina con
PNG89 50 4E 47 0D 0A 1A 0A49 45 4E 44 AE 42 60 82 (chunk IEND y su CRC)
JPEGFF D8 FFFF D9
ZIP (y docx, xlsx, apk)50 4B 03 04 ("PK")50 4B 05 06 y 18 bytes más, si no hay comentario
gzip1F 8B 08no tiene marca de fin

Ojo con el ZIP: cada archivo de adentro empieza con PK 03 04, así que uno con dos archivos tiene dos firmas de inicio.

Ficha de xxd

xxd viene con Vim y muestra posición, bytes en hexadecimal y texto.

xxd [-s INICIO] [-l LARGO] [-r -p] ARCHIVO
OpciónQué haceEjemplo
-sEmpieza en ese byte (seek)xxd -s 4096 usb.img
-lMuestra solo esa cantidad de bytesxxd -l 64 usb.img
-r -pAl revés: convierte texto hex en bytesecho 686f6c61 | xxd -r -p

Ficha de grep para bytes

xxd usb.img | grep '504b 0304' solo encuentra firmas alineadas con los grupos de dos bytes de xxd y que no queden partidas entre dos líneas. Para el desplazamiento exacto de cualquier firma:

LC_ALL=C grep -obUaP 'PATRON' ARCHIVO
OpciónQué hace
-o y -bImprime solo lo encontrado, precedido de su posición en bytes
-a y -UTrata el binario como texto, sin tocar los fines de línea
-PExpresiones de Perl, donde \x89 es el byte 0x89

Agregue | cut -d: -f1 para quedarse solo con los números.

Ficha de dd

dd toma su nombre de la instrucción DD (data definition) del JCL de IBM. Copia bytes; con él se recorta.

dd if=ENTRADA of=SALIDA bs=TAMANO skip=N count=N
OpciónQué haceEjemplo
if / ofArchivo de entrada y de salidaif=usb.img of=foto.png
bs=1Bloques de 1 byte: skip y count cuentan bytesbs=1 skip=4096
countCuántos bloques copiarcount=2048
status=noneCalla el resumen finalstatus=none

Con imágenes de gigas, bs=1 es lentísimo: use bs=4M iflag=skip_bytes,count_bytes.

Errores frecuentes

$ grep -obUaP '\x89PNG' usb.img
$

Ni salida ni error. Con locale UTF-8, el de Ubuntu, \x89 es un carácter Unicode y no un byte: anteponga LC_ALL=C. Tampoco incluya el \r\n de la firma del PNG, porque grep trabaja por líneas.

$ unzip -l usb.img
Archive:  usb.img
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.

unzip busca el final del zip solo cerca del final del archivo, y detrás quedan decenas de KB de imagen. Primero se recorta, después se abre.