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
| Tipo | Empieza con (hex) | Termina con |
|---|---|---|
| PNG | 89 50 4E 47 0D 0A 1A 0A | 49 45 4E 44 AE 42 60 82 (chunk IEND y su CRC) |
| JPEG | FF D8 FF | FF D9 |
| ZIP (y docx, xlsx, apk) | 50 4B 03 04 ("PK") | 50 4B 05 06 y 18 bytes más, si no hay comentario |
| gzip | 1F 8B 08 | no 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ón | Qué hace | Ejemplo |
|---|---|---|
-s | Empieza en ese byte (seek) | xxd -s 4096 usb.img |
-l | Muestra solo esa cantidad de bytes | xxd -l 64 usb.img |
-r -p | Al revés: convierte texto hex en bytes | echo 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ón | Qué hace |
|---|---|
-o y -b | Imprime solo lo encontrado, precedido de su posición en bytes |
-a y -U | Trata el binario como texto, sin tocar los fines de línea |
-P | Expresiones 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ón | Qué hace | Ejemplo |
|---|---|---|
if / of | Archivo de entrada y de salida | if=usb.img of=foto.png |
bs=1 | Bloques de 1 byte: skip y count cuentan bytes | bs=1 skip=4096 |
count | Cuántos bloques copiar | count=2048 |
status=none | Calla el resumen final | status=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.