¿Cómo comparo archivos binarios en Linux?

304

Necesito comparar dos archivos binarios y obtener el resultado en el formulario:

<fileoffset-hex> <file1-byte-hex> <file2-byte-hex>

por cada byte diferente. Entonces si file1.bines

  00 90 00 11

en forma binaria y file2.bines

  00 91 00 10

Quiero conseguir algo como

  00000001 90 91
  00000003 11 10

¿Hay alguna manera de hacer esto en Linux? Lo sé, cmp -lpero utiliza un sistema decimal para desplazamientos y octal para bytes que me gustaría evitar.

bertieb
fuente
99
básicamente estás buscando "diferencias binarias". Me imagino una línea de comando realmente fea con un od...
quack quixote
2
@quack quijote: ¿Qué tiene de feo un one-liner? ;)
Bobby
xdelta.org funciona bastante bien. Quizás valdría la pena echarle un vistazo.
thatjuan
Debido a que no puede responder esta pregunta (ya que no es un usuario), votaré para cerrar. Un diferencial binario, como se solicita explícitamente aquí, no es del todo útil, y me inclino a pensar que quiere algo útil, si inserta un byte al comienzo del archivo, ¿todos los bytes deben marcarse como diferentes? Sin saber eso, esto es simplemente demasiado vago.
Evan Carroll
2
@EvanCarroll Si cree que la pregunta está fuera de tema, ¿por qué la responde?
DavidPostill

Respuestas:

174

Esto imprimirá el desplazamiento y los bytes en hexadecimal:

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'

O haga $1-1que el primer desplazamiento impreso comience en 0.

cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'

Desafortunadamente, strtonum()es específico de GAWK, por lo que para otras versiones de awk, por ejemplo, mawk, necesitará usar una función de conversión de octal a decimal. Por ejemplo,

cmp -l file1.bin file2.bin | mawk 'function oct2dec(oct,     dec) {for (i = 1; i <= length(oct); i++) {dec *= 8; dec += substr(oct, i, 1)}; return dec} {printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)}'

Desglosado por legibilidad:

cmp -l file1.bin file2.bin |
    mawk 'function oct2dec(oct,    dec) {
              for (i = 1; i <= length(oct); i++) {
                  dec *= 8;
                  dec += substr(oct, i, 1)
              };
              return dec
          }
          {
              printf "%08X %02X %02X\n", $1, oct2dec($2), oct2dec($3)
          }'
Dennis Williamson
fuente
3
@gertvdijk: strtonumes específico de GAWK. Creo que Ubuntu utilizó anteriormente GAWK como predeterminado, pero cambió en algún momento a mawk. En cualquier caso, GAWK se puede instalar y establecer en el valor predeterminado (ver también man update-alternatives). Vea mi respuesta actualizada para una solución que no requiere strtonum.
Dennis Williamson
¿Por qué no simplemente comparar el sha256sum de ambos archivos?
Rodrigo
1
@Rodrigo: Ese y otros métodos solo mostrarán si los archivos son diferentes. Mi respuesta cumple con el requisito del OP para mostrar realmente cuáles son las diferencias.
Dennis Williamson
¡Por supuesto! Lo siento, estaba tan preocupado por MI problema que apenas leí los OP. Gracias.
Rodrigo
166

Como ~ quack señaló:

 % xxd b1 > b1.hex
 % xxd b2 > b2.hex

Y entonces

 % diff b1.hex b2.hex

o

 % vimdiff b1.hex b2.hex
akira
fuente
70
En Bash: diff <(xxd b1) <(xxd b2)pero el formato de salida de este (o el suyo) no se acerca a lo que solicitó el OP.
Dennis Williamson
66
con vimdiff es, coloreará los bytes en las líneas donde difieren los dos 'archivos'
akira
Aww, ¿por qué no pensé en eso? Y estoy seguro de que también he usado esta técnica en el pasado.
njd
1
Esto funcionó muy bien para mí (con opendiffOS X en lugar de vimdiff): la vista predeterminada xxdproporciona el motor diff en la pista comparando byte por byte. Con hexadecimal simple (en bruto) simplemente con ajuste de columna fold, diffintentaría doblar / agrupar cosas aleatorias en los archivos que estaba comparando.
natevw
1
Este comando no funciona bien para la eliminación de la adición de bytes, ya que cada línea que sigue se desalineará y se verá modificada por diff. La solución es poner 1 byte por línea y eliminar la columna de la dirección propuesta por John Lawrence Aspden y yo .
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
98

diff + xxd

Pruebe diffcon la siguiente combinación de sustitución de procesos zsh / bash:

diff -y <(xxd foo1.bin) <(xxd foo2.bin)

Dónde:

  • -y le muestra las diferencias de lado a lado (opcional).
  • xxd es la herramienta CLI para crear una salida hexdump del archivo binario.
  • Agregue -W200a diffpara una salida más amplia (de 200 caracteres por línea).
  • Para colores, use colordiffcomo se muestra a continuación.

colordiff + xxd

Si lo ha hecho colordiff, puede colorear la diffsalida, por ejemplo:

colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)

De lo contrario, instalar a través de: sudo apt-get install colordiff.

Salida de muestra:

salida de archivo binario en terminal - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  colordiff

vimdiff + xxd

También puede usar vimdiff, por ejemplo

vimdiff <(xxd foo1.bin) <(xxd foo2.bin)

Consejos:

  • si los archivos son demasiado grandes, agregue un límite (por ejemplo -l1000) para cadaxxd
kenorb
fuente
11
El comando se puede simplificar como colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
Golem
3
Si no tiene colordiff, esto hará lo mismo sin colores:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee
55
Si solo desea saber si ambos archivos son realmente iguales, puede usar el interruptor -qo --brief, que solo mostrará la salida cuando los archivos difieran.
Stefan van den Akker
1
cree una función xxddiffpara esto con:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
rubo77
2
¡Excelente! aún así, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - va a hacer un trabajo de buena enoug
ribamar
56

Hay una herramienta llamada DHEX que puede hacer el trabajo, y hay otra herramienta llamada VBinDiff .

Para un enfoque estrictamente de línea de comandos, intente jojodiff .

njd
fuente
8
DHEX es increíble, lo que quieres hacer es comparar binarios. Aliméntelo con dos archivos y lo llevará directamente a una vista comparativa, resaltando las diferencias, con la capacidad de pasar a la siguiente diferencia. También es capaz de trabajar con terminales grandes, lo cual es muy útil en monitores de pantalla ancha.
Marcin
77
Prefiero VBinDiff. DHEX está utilizando la CPU incluso cuando está inactivo, creo que se está redibujando todo el tiempo o algo así. Sin embargo, VBinDiff no funciona con terminales anchas. Pero las direcciones se vuelven raras con terminales anchas de todos modos, ya que tiene más de 16 bytes por fila.
Janus Troelsen
1
vbindiff nos permite editar el archivo, ¡gracias!
Acuario Power
2
Los archivos comprimidos de @DanielBeauyat serán completamente diferentes después de que encuentre el primer byte diferente. No es probable que la salida sea útil.
Mark Ransom
2
@ 1111161171159459134 jdiff es parte de un "conjunto" de programas para sincronizar y parchear las diferencias encontradas por jdiff. Pero, como dijo Mark Ransom, eso generalmente no sería prudente en archivos comprimidos; la excepción son los formatos comprimidos "sincronizables" (como el producido por gzip --rsyncable), en el que las pequeñas diferencias en los archivos no comprimidos deberían tener un efecto limitado en el archivo comprimido.
hmijail
27

Método que funciona para la adición / eliminación de bytes

diff <(od -An -tx1 -w1 -v file1) \
     <(od -An -tx1 -w1 -v file2)

Genere un caso de prueba con una sola eliminación del byte 64:

for i in `seq 128`; do printf "%02x" "$i"; done | xxd -r -p > file1
for i in `seq 128`; do if [ "$i" -ne 64 ]; then printf "%02x" $i; fi; done | xxd -r -p > file2

Salida:

64d63
<  40

Si también quieres ver la versión ASCII del personaje:

bdiff() (
  f() (
    od -An -tx1c -w1 -v "$1" | paste -d '' - -
  )
  diff <(f "$1") <(f "$2")
)

bdiff file1 file2

Salida:

64d63
<   40   @

Probado en Ubuntu 16.04.

Prefiero odsobre xxdporque:

  • que es POSIX , xxdno está (viene con Vim)
  • tiene el -Anpara eliminar la columna de dirección sin awk.

Explicación del comando:

  • -Anelimina la columna de la dirección. Esto es importante; de ​​lo contrario, todas las líneas serían diferentes después de la adición / eliminación de un byte.
  • -w1pone un byte por línea, para que diff pueda consumirlo. Es crucial tener un byte por línea, o de lo contrario, cada línea después de una eliminación quedaría desfasada y diferente. Desafortunadamente, esto no es POSIX, pero está presente en GNU.
  • -tx1 es la representación que desea, cambie a cualquier valor posible, siempre que mantenga 1 byte por línea.
  • -vevita la abreviatura de repetición de asterisco *que podría interferir con la diferencia
  • paste -d '' - -se une cada dos líneas. Lo necesitamos porque el hex y ASCII van en líneas adyacentes separadas. Tomado de: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • utilizamos paréntesis ()para definir en bdifflugar de {}limitar el alcance de la función interna f, consulte también: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Ver también:

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente
13

Respuesta corta

vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin)

Al usar hexdumps y text diff para comparar archivos binarios, especialmente xxd, las adiciones y eliminaciones de bytes se convierten en cambios en el direccionamiento que pueden dificultar la visualización. Este método le dice a xxd que no envíe direcciones y que solo envíe un byte por línea, que a su vez muestra exactamente qué bytes se cambiaron, agregaron o eliminaron. Puede encontrar las direcciones más adelante buscando las secuencias interesantes de bytes en un hexdump (salida de xxd first.bin) más "normal" .

Evgeny
fuente
(Por supuesto, uno puede usar en difflugar de vimdiff).
VasyaNovikov
11

Recomiendo hexdump para volcar archivos binarios a formato de texto y kdiff3 para visualización diferencial.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex
BugoK
fuente
2
Incluso aquí en bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)sin necesidad de crear archivos myfile1.hexy myfile2.hex.
Hastur
5

El hexdiffes un programa diseñado para hacer exactamente lo que estás buscando.

Uso:

hexdiff file1 file2

Muestra el hexadecimal (y ASCII de 7 bits) de los dos archivos uno encima del otro, con cualquier diferencia resaltada. Mire man hexdifflos comandos para moverse en el archivo, y se qcerrará un simple .

Mick
fuente
44
Pero hace un trabajo bastante malo cuando se trata de la parte de comparación. Si inserta algunos bytes en un archivo, marcará todos los bytes después como cambios
Murmel
y hexdiff no está disponible a través de apt-get en Ubuntu 16.4
rubo77
1
@Murmel mientras estoy de acuerdo, ¿no es eso lo que se pregunta aquí?
Evan Carroll
@EvanCarroll es cierto, y por lo tanto dejé un comentario (solo) y no
voté en contra
Tampoco rechacé votar a Mick, pero estoy de acuerdo contigo y respondí aquí superuser.com/a/1373977/11116 porque parece probable que esta mala pregunta se reformará o se cerrará.
Evan Carroll
3

Puede que no responda estrictamente la pregunta, pero lo uso para diferentes binarios:

gvim -d <(xxd -c 1 ~/file1.bin | awk '{print $2, $3}') <(xxd -c 1 ~/file2.bin | awk '{print $2, $3}')

Imprime ambos archivos como valores hexadecimales y ASCII , un byte por línea, y luego usa la función diff de Vim para representarlos visualmente.

John Lawrence Aspden
fuente
0

dhex http://www.dettus.net/dhex/

DHEX es más que un simple editor hexadecimal: incluye un modo diff, que se puede usar para comparar dos archivos binarios de manera fácil y conveniente. Dado que está basado en ncurses y es temático, puede ejecutarse en cualquier número de sistemas y escenarios. Con su utilización de registros de búsqueda, es posible rastrear cambios en diferentes iteraciones de archivos fácilmente.

Vincent Vega
fuente
¡Bienvenido a SuperUser! Aunque parece que este software podría resolver el problema del OP, la publicidad pura está muy mal vista en la red de Stack Exchange. Si está afiliado al editor de este software, revele este hecho. E intenta reescribir tu publicación para que parezca menos un comercial. Gracias.
Nathan.Eilisha Shiraini
No estoy afiliado a dhex de ninguna manera. Copié la descripción del autor en la publicación porque hay un límite mínimo de duración de la publicación
Vincent Vega
Ya mencionado en: superuser.com/a/125390/128124
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
0

Puede usar la herramienta gvimdiff que se incluye en el paquete vim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

Luego puede comparar 2 archivos hexadecimales con los siguientes comandos:

ubuntu> gvimdiff <hex-file1> <hex-file2>

Eso es todo. Espero que ayude!

agrietado
fuente
0

La herramienta de análisis de firmware binwalktambién tiene esto como una característica a través de su opción de línea de comando -W/--hexdump que ofrece opciones como mostrar solo los diferentes bytes:

    -W, --hexdump                Perform a hexdump / diff of a file or files
    -G, --green                  Only show lines containing bytes that are the same among all files
    -i, --red                    Only show lines containing bytes that are different among all files
    -U, --blue                   Only show lines containing bytes that are different among some files
    -w, --terse                  Diff all files, but only display a hex dump of the first file

En el ejemplo de OP al hacer binwalk -W file1.bin file2.bin:

binwalk -W file1.bin file2.bin

phk
fuente
-2

El producto de código abierto en Linux (y todo lo demás) es Radare, que proporciona radiff2explícitamente para este propósito. Voté para cerrar esto porque yo y otros tenemos la misma pregunta, en la pregunta que usted hace

por cada byte diferente

Eso es una locura sin embargo. Como se le preguntó, si inserta un byte en el primer byte en el archivo, encontrará que cada byte posterior es diferente y, por lo tanto, el diff repetiría todo el archivo, para una diferencia real de un byte.

Un poco más práctico es radiff -O. El -Oes para "" El código difiere con todos los bytes en lugar de solo los bytes fijos del código de operación ""

0x000000a4 0c01 => 3802 0x000000a4
0x000000a8 1401 => 3802 0x000000a8
0x000000ac 06 => 05 0x000000ac
0x000000b4 02 => 01 0x000000b4
0x000000b8 4c05 => 0020 0x000000b8
0x000000bc 4c95 => 00a0 0x000000bc
0x000000c0 4c95 => 00a0 0x000000c0

Al igual que IDA Pro, Radare es una herramienta primaria para el análisis binario, también puede mostrar diferencias delta con -d, o mostrar los bytes desmontados en lugar de hexadecimal con -D.

Sin embargo, si está haciendo este tipo de preguntas, consulte

Evan Carroll
fuente