Come faccio a confrontare i file binari in Linux?


304

Devo confrontare due file binari e ottenere l'output nel modulo:

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

per ogni byte diverso. Quindi se lo file1.binè

  00 90 00 11

in forma binaria ed file2.binè

  00 91 00 10

Voglio ottenere qualcosa del genere

  00000001 90 91
  00000003 11 10

C'è un modo per farlo in Linux? Lo so, cmp -lma utilizza un sistema decimale per gli offset e ottale per i byte che vorrei evitare.


9
stai fondamentalmente cercando "binary diff". posso immaginare qualche riga di comando reeeally brutto-liner con od...
ciarlatano quixote

2
@quack quixote: Cosa c'è di brutto in un one-liner? ;)
Bobby

xdelta.org funziona abbastanza bene. Forse varrebbe la pena darci un'occhiata.
thatjuan,

Poiché non puoi rispondere a questa domanda (dato che non sei un utente), sto votando per chiudere. Un diff binario come esplicitamente richiesto qui non è affatto utile, e sono propenso a pensare che tu voglia qualcosa di utile, se inserisci un byte all'inizio del file dovrebbero essere contrassegnati come diversi? Senza saperlo, questo è semplicemente troppo vago.
Evan Carroll,

2
@EvanCarroll Se pensi che la domanda sia fuori tema, perché stai rispondendo?
DavidPostill

Risposte:


174

Questo stamperà l'offset e i byte in esadecimale:

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

Oppure fai $1-1in modo che il primo offset stampato inizi da 0.

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

Sfortunatamente, strtonum()è specifico di GAWK, quindi per altre versioni di awk, ad esempio mawk, sarà necessario utilizzare una funzione di conversione da ottale a decimale. Per esempio,

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)}'

Risolto per leggibilità:

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)
          }'

3
@gertvdijk: strtonumè specifico di GAWK. Credo che Ubuntu abbia usato GAWK come predefinito, ma a un certo punto è passato a mawk. In ogni caso, GAWK può essere installato e impostato sul valore predefinito (vedi anche man update-alternatives). Vedi la mia risposta aggiornata per una soluzione che non richiede strtonum.
Dennis Williamson,

Perché non confrontare semplicemente lo sha256sum di entrambi i file?
Rodrigo,

1
@Rodrigo: Questo e vari altri metodi mostreranno solo se i file differiscono. La mia risposta soddisfa il requisito del PO di mostrare effettivamente quali sono le differenze.
Dennis Williamson, il

Ovviamente! Mi dispiace, ero così preoccupato per il MIO problema che ho appena letto gli OP. Grazie.
Rodrigo,

166

Come ha sottolineato ~ Quack :

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

E poi

 % diff b1.hex b2.hex

o

 % vimdiff b1.hex b2.hex

70
In Bash: diff <(xxd b1) <(xxd b2)ma il formato di output di questo (o il tuo) non è affatto vicino a ciò che l'OP ha richiesto.
Dennis Williamson,

6
con vimdiff lo è, colora i byte nelle righe in cui i due 'file' differiscono
Akira

Aww, perché non ci ho pensato? E sono sicuro di aver usato questa tecnica anche in passato.
njd,

1
Questo ha funzionato benissimo per me (con opendiffsu OS X anziché vimdiff) - la visualizzazione predefinita xxdfornisce il motore diff in pista confrontando byte per byte. Con un esadecimale semplice (grezzo) che si adattava semplicemente alla colonna fold, diffprovavo a piegare / raggruppare cose casuali nei file che stavo confrontando.
natevw,

1
Questo comando non funziona bene per la rimozione dell'aggiunta di byte, poiché ogni riga che segue sarà disallineata e vista come modificata da diff. La soluzione è mettere 1 byte per riga e rimuovere la colonna dell'indirizzo come proposto da John Lawrence Aspden e da me .
Ciro Santilli 4 改造 中心 法轮功 六四 事件

98

diff + xxd

Prova diffnella seguente combinazione di sostituzione del processo zsh / bash:

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

Dove:

  • -y mostra le differenze affiancate (facoltativo).
  • xxd è lo strumento CLI per creare un output hexdump del file binario.
  • Aggiungi -W200a diffper output più ampio (di 200 caratteri per riga).
  • Per i colori, utilizzare colordiffcome mostrato di seguito.

colordiff + xxd

Se hai colordiff, può colorare l' diffoutput, ad esempio:

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

In caso contrario, installare tramite: sudo apt-get install colordiff.

Uscita campione:

output del file binario nel terminale - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  colordiff

vimdiff + xxd

Puoi anche usare vimdiff, ad es

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

suggerimenti:

  • se i file sono troppo grandi, aggiungi un limite (ad es. -l1000) per ciascunoxxd

11
Il comando può essere semplificato come colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
Golem,

3
Se non hai colordiff, questo farà la stessa cosa senza colori:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee

5
Se vuoi solo sapere se entrambi i file sono effettivamente uguali, puoi usare l' opzione -qo --brief, che mostrerà l'output solo quando i file differiscono.
Stefan van den Akker,

1
creare una funzione xxddiffper questo con:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
rubo77

2
grande! comunque, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - farà un buon lavoro
enoug

56

C'è uno strumento chiamato DHEX che può fare il lavoro, e c'è un altro strumento chiamato VBinDiff .

Per un approccio rigorosamente a riga di comando, prova jojodiff .


8
DHEX è fantastico, confrontando i binari è quello che vuoi fare. Alimentalo in due file e ti porta direttamente a una vista comparativa, evidenziando le differenze, con una facile capacità di passare alla differenza successiva. Inoltre è in grado di funzionare con terminali di grandi dimensioni, il che è molto utile su monitor widescreen.
Marcin,

7
Preferisco VBinDiff. DHEX utilizza la CPU anche quando è inattivo, penso che ridisegni continuamente o qualcosa del genere. VBinDiff non funziona con terminali larghi però. Ma gli indirizzi diventano comunque strani con terminali ampi, poiché hai più di 16 byte per riga.
Janus Troelsen,

1
vbindiff ci consente di modificare effettivamente il file, grazie!
Aquarius Power

2
I file compressi @DanielBeauyat saranno completamente diversi dopo aver incontrato il primo byte diverso. È probabile che l'output non sia utile.
Mark Ransom,

2
@ 1111161171159459134 jdiff fa parte di una "suite" di programmi per sincronizzare e correggere le differenze rilevate da jdiff. Ma, come diceva Mark Ransom, ciò non sarebbe generalmente saggio sui file compressi; l'eccezione sono i formati compressi "sincronizzabili" (come quello prodotto da gzip --rsyncable), in cui piccole differenze nei file non compressi dovrebbero avere un effetto limitato sul file compresso.
Hmijail,

27

Metodo che funziona per l'aggiunta / eliminazione di byte

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

Genera un caso di test con una singola rimozione 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

Produzione:

64d63
<  40

Se vuoi vedere anche la versione ASCII del personaggio:

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

bdiff file1 file2

Produzione:

64d63
<   40   @

Testato su Ubuntu 16.04.

Preferisco odpiù xxdperché:

  • esso è POSIX , xxdnon è (viene fornito con Vim)
  • deve -Anrimuovere la colonna dell'indirizzo senza awk.

Spiegazione del comando:

  • -Anrimuove la colonna dell'indirizzo. Questo è importante, altrimenti tutte le righe differirebbero dopo un'aggiunta / rimozione di byte.
  • -w1mette un byte per riga, in modo che diff possa consumarlo. È fondamentale disporre di un byte per riga, altrimenti ogni riga dopo una cancellazione diventerebbe sfasata e diversa. Sfortunatamente, questo non è POSIX, ma presente in GNU.
  • -tx1 è la rappresentazione che desideri, passa a qualsiasi valore possibile, purché mantieni 1 byte per riga.
  • -vimpedisce l'abbreviazione della ripetizione dell'asterisco *che potrebbe interferire con il diff
  • paste -d '' - -unisce ogni due righe. Ne abbiamo bisogno perché l'esagono e l'ASCII vanno in linee adiacenti separate. Tratto da: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • usiamo la parentesi ()per definire bdiffinvece di {}limitare l'ambito della funzione interna f, vedi anche: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Guarda anche:


13

Risposta breve

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

Quando si utilizzano hexdump e diff di testo per confrontare i file binari, in particolare xxd, le aggiunte e le rimozioni di byte diventano spostamenti nell'indirizzamento che potrebbero rendere difficile la visualizzazione. Questo metodo dice a xxd di non emettere gli indirizzi e di produrre solo un byte per riga, che a sua volta mostra esattamente quali byte sono stati modificati, aggiunti o rimossi. È possibile trovare gli indirizzi in un secondo momento cercando le sequenze interessanti di byte in un hexdump più "normale" (output di xxd first.bin).


(Certo, si può usare al diffposto di vimdiff.)
VasyaNovikov il

11

Consiglierei hexdump per scaricare i file binari in formato testuale e kdiff3 per la visualizzazione diff.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex

2
Anche qui a bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)senza bisogno di creare file myfile1.hexe myfile2.hex.
Hastur,

5

Il hexdiffè un programma progettato per fare esattamente quello che stai cercando.

Uso:

hexdiff file1 file2

Visualizza l'esadecimale (e ASCII a 7 bit) dei due file uno sopra l'altro, con eventuali differenze evidenziate. Cerca man hexdiffi comandi per spostarti nel file e qverrà chiuso un semplice .


4
Ma fa un lavoro piuttosto negativo quando si tratta della parte di confronto. Se si inseriscono alcuni byte in un file, in seguito verranno contrassegnati tutti i byte come modifiche
Murmel,

e hexdiff non è disponibile tramite apt-get su Ubuntu 16.4
rubo77

1
@Murmel mentre sono d'accordo, non è quello che viene chiesto qui?
Evan Carroll,

@EvanCarroll vero, e quindi ho lasciato un commento (solo) e non ho
votato in basso

Anche io non ho votato male Mick, ma sono d'accordo con te e ho risposto qui superuser.com/a/1373977/11116 perché sembra probabile che questa brutta domanda venga riformata o chiusa.
Evan Carroll,

3

Potrebbe non rispondere rigorosamente alla domanda, ma io lo uso per diversi binari:

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

Stampa entrambi i file come valori esadecimali e ASCII , un byte per riga, quindi utilizza la funzione diff di Vim per renderli visivamente.


0

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

DHEX è più di un semplice editor esadecimale: include una modalità diff, che può essere utilizzata per confrontare facilmente e comodamente due file binari. Poiché è basato su ncurses ed è tematico, può essere eseguito su qualsiasi numero di sistemi e scenari. Con il suo utilizzo dei log di ricerca, è possibile monitorare facilmente le modifiche in diverse iterazioni di file.


Benvenuto in SuperUser! Sebbene questo software sembri in grado di risolvere il problema del PO, la pubblicità pura è fortemente disapprovata sulla rete Stack Exchange. Se sei affiliato all'editore di questo software, ti preghiamo di rivelare questo fatto. E prova a riscrivere il tuo post in modo che appaia meno come una pubblicità. Grazie.
Nathan.Eilisha Shiraini,

Non sono affiliato al dhex in alcun modo. Ho copiato la descrizione dell'autore nel post perché esiste un limite di lunghezza minimo del post
Vincent Vega,


0

Puoi usare lo strumento gvimdiff incluso nel pacchetto vim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

Quindi puoi confrontare 2 file esadecimali usando i seguenti comandi:

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

Tutto qui. Spero che ti aiuti!


0

Lo strumento di analisi del firmware ha binwalkanche questa funzionalità come opzione tramite l' opzione -W/ --hexdumpriga di comando che offre opzioni che mostrano solo i diversi byte:

    -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

Nell'esempio di OP quando si fa binwalk -W file1.bin file2.bin:

binwalk -W file1.bin file2.bin



-2

Il prodotto open source su Linux (e tutto il resto) è Radare che fornisce radiff2esplicitamente a tale scopo. Ho votato per chiudere perché io e gli altri abbiamo la stessa domanda, nella domanda che poni

per ogni byte diverso

È folle però. Perché, come richiesto, se si inserisce un byte nel primo byte nel file, si troverà che ogni byte successivo era diverso e quindi il diff ripeterebbe l'intero file, per una differenza effettiva di un byte.

È leggermente più pratico radiff -O. Il -Oè per "" Do codice diffing con tutti i byte invece che solo i byte di codice operativo fisso ""

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

Come IDA Pro, Radare è uno strumento primario per l'analisi binaria, puoi anche mostrare delta diffing con -do visualizzare i byte disassemblati invece di hex con -D.

Se stai facendo questo tipo di domande, controlla

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.