Comment comparer les fichiers binaires sous Linux?

304

Je dois comparer deux fichiers binaires et obtenir le résultat sous la forme:

<fileoffset-hex> <fichier1 octets-hex> <fichier2 octets-hex>

pour chaque octet différent. Donc si file1.binest

  00 90 00 11

sous forme binaire et file2.binest

  00 91 00 10

Je veux obtenir quelque chose comme

  00000001 90 91
  00000003 11 10

Y a-t-il un moyen de faire cela sous Linux? Je connais cmp -lmais il utilise un système décimal pour les décalages et octal pour les octets que je voudrais éviter.

Bertieb
la source
9
vous êtes fondamentalement à la recherche de "diff binaire". Je peux imaginer un one-liner avec une ligne de commande vraiment moche od...
Quack quixote
2
@quack quixote: Qu'est-ce qui est moche dans un one-liner? ;)
Bobby
xdelta.org fonctionne assez bien. Cela vaudrait peut-être la peine d'y jeter un coup d'œil.
thatjuan
Parce que vous ne pouvez pas répondre à cette question (étant donné que vous n'êtes pas un utilisateur), je vote pour la fermeture. Un diff binaire tel que demandé explicitement ici n'est pas du tout utile, et j'ai tendance à penser que vous voulez quelque chose d'utile. Si vous insérez un octet au début du fichier, tous les octets doivent-ils être marqués comme étant différents? Sans le savoir, c'est simplement trop vague.
Evan Carroll
2
@ EvanCarroll Si vous pensez que la question est hors sujet, pourquoi y répondez-vous?
DavidPostill

Réponses:

174

Ceci imprimera le décalage et les octets au format hexadécimal:

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

Ou bien, faites $1-1que le premier offset imprimé commence à 0.

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

Malheureusement, il strtonum()est spécifique à GAWK. Par conséquent, pour les autres versions d'awk, telles que mawk, vous devrez utiliser une fonction de conversion octale en décimale. Par exemple,

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

Éclaté pour plus de lisibilité:

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
la source
3
@gertvdijk: strtonumest spécifique à GAWK. Je pense qu'Ubuntu utilisait auparavant GAWK par défaut, mais a basculé à un moment donné mawk. Dans tous les cas, GAWK peut être installé et configuré par défaut (voir aussi man update-alternatives). Voir ma réponse mise à jour pour une solution qui ne nécessite pas strtonum.
Dennis Williamson
Pourquoi ne pas simplement comparer le sha256sum des deux fichiers?
Rodrigo
1
@Rodrigo: Cela et diverses autres méthodes montreront simplement si les fichiers diffèrent. Ma réponse répond à l'exigence du PO de montrer réellement les différences.
Dennis Williamson
Bien sûr! Désolé, mon problème m'inquiétait tellement que j'ai à peine lu les PO. Je vous remercie.
Rodrigo
166

Comme ~ charlatan l'a fait remarquer:

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

Puis

 % diff b1.hex b2.hex

ou

 % vimdiff b1.hex b2.hex
Akira
la source
70
In Bash: diff <(xxd b1) <(xxd b2)mais le format de sortie de celui-ci (ou du vôtre) est loin de ce que l'OP a demandé.
Dennis Williamson
6
avec vimdiff, il colorera les octets dans les lignes où se différencient les deux fichiers
akira
Aww, pourquoi je n'y avais pas pensé? Et je suis sûr que j'ai déjà utilisé cette technique par le passé.
Njd
1
Cela fonctionnait très bien pour moi (avec opendiffOS X au lieu de vimdiff) - la vue par défaut xxdpermet au moteur de diff de rester sur la bonne voie en comparant octet par octet. Avec un hexa brut (brut) simplement ajusté avec la colonne fold, diffessaierait de plier / grouper des éléments aléatoires dans les fichiers que je comparais.
Natevw
1
Cette commande ne fonctionne pas bien pour la suppression d’octets, car chaque ligne suivante sera mal alignée et sera modifiée par diff. La solution consiste à mettre 1 octet par ligne et à supprimer la colonne adresse proposée par John Lawrence Aspden et moi-même .
Ciro Santilli a annoncé le blog '
98

diff + xxd

Essayez diffla combinaison suivante de substitution de processus zsh / bash:

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

Où:

  • -y vous montre les différences côte à côte (facultatif).
  • xxd est un outil CLI pour créer une sortie hexdump du fichier binaire.
  • Ajouter -W200à diffpour une sortie plus large (200 caractères par ligne).
  • Pour les couleurs, utilisez colordiffcomme indiqué ci-dessous.

colordiff + xxd

Si vous en avez colordiff, il peut coloriser la diffsortie, par exemple:

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

Sinon l' installation via: sudo apt-get install colordiff.

Exemple de sortie:

Sortie du fichier binaire dans le terminal - diff -y <(xxd foo1.bin) <(xxd foo2.bin) |  Colordiff

vimdiff + xxd

Vous pouvez également utiliser vimdiff, par exemple

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

Conseils:

  • si les fichiers sont trop gros, ajouter une limite (par exemple -l1000) pour chaquexxd
Kenorb
la source
11
La commande peut être simplifiée comme colordiff -y <(xxd foo1.bin) <(xxd foo2.bin).
Golem
3
Si vous n'avez pas colordiff, cela fera la même chose sans couleurs:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Rock Lee
5
Si vous voulez simplement savoir si les deux fichiers sont réellement identiques, vous pouvez utiliser le commutateur -qou --brief, qui affichera la sortie uniquement lorsque les fichiers diffèrent.
Stefan van den Akker
1
créez une fonction xxddiffpour cela avec:xxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
rubo77
2
génial! encore, diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - va faire un bon travail enoug
ribamar
57

Il existe un outil appelé DHEX qui peut faire l'affaire et un autre outil appelé VBinDiff .

Pour une approche strictement en ligne de commande, essayez jojodiff .

njd
la source
8
DHEX est génial, c'est que comparer les fichiers binaires est ce que vous voulez faire. Chargez-la en deux fichiers et vous obtiendrez une vue comparative, mettant en évidence les différences, avec une capacité facile à passer à la différence suivante. En outre, il est capable de travailler avec de grands terminaux, ce qui est très utile sur les moniteurs à écran large.
Marcin
7
Je préfère VBinDiff. DHEX utilise le processeur même au ralenti, je pense que ça redessine tout le temps ou quelque chose comme ça. VBinDiff ne fonctionne cependant pas avec les terminaux larges. Mais les adresses deviennent quand même bizarres avec les terminaux larges, puisque vous avez plus de 16 octets par ligne.
Janus Troelsen
1
vbindiff nous permet d’éditer le fichier, merci!
Aquarius Power
2
Les fichiers compressés @DanielBeauyat seront complètement différents lorsque vous rencontrerez le premier octet différent. La sortie ne sera probablement pas utile.
Mark Ransom
2
@ 1111161171159459134 jdiff fait partie d'une "suite" de programmes permettant de synchroniser et de corriger les différences trouvées par jdiff. Mais, comme l'a dit Mark Ransom, ce ne serait généralement pas judicieux pour les fichiers compressés; l'exception concerne les formats compressés "synchronisables" (comme celui produit par gzip --rsyncable), dans lesquels de petites différences dans les fichiers non compressés devraient avoir un effet limité sur le fichier compressé.
hmijail
27

Méthode qui fonctionne pour l'ajout / la suppression d'octets

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

Générez un scénario de test avec une seule suppression de l'octet 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

Sortie:

64d63
<  40

Si vous souhaitez également voir la version ASCII du caractère:

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

bdiff file1 file2

Sortie:

64d63
<   40   @

Testé sur Ubuntu 16.04.

Je préfère odplus xxdparce que:

  • c'est POSIX , xxdn'est pas (livré avec Vim)
  • a le -Anpour supprimer la colonne d'adresse sans awk.

Explication de la commande:

  • -Ansupprime la colonne d'adresse. C'est important sinon toutes les lignes seraient différentes après l'ajout / le retrait d'un octet.
  • -w1met un octet par ligne, pour que diff puisse le consommer. Il est crucial d’avoir un octet par ligne, sinon chaque ligne après une suppression deviendrait déphasée et différerait. Malheureusement, ce n'est pas POSIX, mais présent dans GNU.
  • -tx1 est la représentation que vous voulez, changez pour n'importe quelle valeur possible, tant que vous gardez 1 octet par ligne.
  • -vempêche l'abréviation de répétition astérisque *qui pourrait interférer avec le diff
  • paste -d '' - -rejoint toutes les deux lignes. Nous en avons besoin parce que l'hex et ASCII vont dans des lignes adjacentes séparées. Tiré de: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • nous utilisons des parenthèses ()pour définir bdiffau lieu de {}limiter la portée de la fonction interne f, voir aussi: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash

Voir également:

Ciro Santilli 改造 中心 六四 事件
la source
13

Réponse courte

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

Lorsque vous utilisez hexdumps et text diff pour comparer des fichiers binaires, en particulier xxd, les ajouts et suppressions d'octets deviennent des décalages dans l'adressage, ce qui peut rendre la lecture difficile. Cette méthode indique à xxd de ne pas afficher les adresses et de ne générer qu'un seul octet par ligne, ce qui indique exactement quels octets ont été modifiés, ajoutés ou supprimés. Vous pouvez trouver les adresses plus tard en recherchant les séquences d'octets intéressantes dans un hexdump plus "normal" (sortie de xxd first.bin).

Evgeny
la source
(Bien sûr, on peut utiliser diffau lieu de vimdiff.)
VasyaNovikov
11

Je recommanderais hexdump pour vider les fichiers binaires au format texte et kdiff3 pour les diff.

hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex
BugoK
la source
2
Même ici à Bash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)sans avoir besoin de créer des fichiers myfile1.hexet myfile2.hex.
Hastur
5

Le hexdiffest un programme conçu pour faire exactement ce que vous recherchez.

Usage:

hexdiff file1 file2

Il affiche le format hexadécimal (et ASCII 7 bits) des deux fichiers superposés, avec les différences mises en évidence. Recherchez man hexdiffles commandes à déplacer dans le fichier et un simple qquittera.

Mick
la source
4
Mais il fait un très mauvais travail en ce qui concerne la comparaison. Si vous insérez des octets dans un fichier, tous les octets seront ensuite marqués comme des modifications
Murmel
et hexdiff n'est pas disponible via apt-get sur Ubuntu 16.4
rubo77
1
@Murmel pendant que je suis d'accord, n'est-ce pas ce qui est demandé ici?
Evan Carroll
@EvanCarroll true, et donc j'ai laissé un commentaire (seulement) et n'a pas
voté
J'ai également voté contre Mick, mais je suis d'accord avec vous et j'ai répondu à la question superuser.com/a/1373977/11116 car il semble probable que cette mauvaise question sera réformée ou fermée.
Evan Carroll
3

Cela ne répond peut-être pas strictement à la question, mais je l'utilise pour les binaires différents:

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

Il imprime les deux fichiers en tant que valeurs hexadécimales et ASCII , un octet par ligne, puis utilise la fonction de différenciation de Vim pour les rendre visuellement.

John Lawrence Aspden
la source
0

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

DHEX est un autre éditeur hexadécimal: il comprend un mode diff qui permet de comparer facilement et commodément deux fichiers binaires. Comme il est basé sur ncurses et qu'il est possible de les utiliser, il peut être exécuté sur un nombre quelconque de systèmes et de scénarios. Grâce à son utilisation des journaux de recherche, il est possible de suivre facilement les modifications apportées à différentes itérations de fichiers.

Vincent Vega
la source
Bienvenue sur SuperUser! Bien que ce logiciel semble pouvoir résoudre le problème du PO, la publicité pure est vivement mal vue sur le réseau Stack Exchange. Si vous êtes affilié à l'éditeur de ce logiciel, veuillez divulguer ce fait. Et essayez de réécrire votre message pour qu'il ressemble moins à une publicité. Je vous remercie.
Nathan.Eilisha Shiraini
Je ne suis en aucun cas affilié à Dhex. J'ai copié la description de l'auteur dans le message car il existe une limite de longueur minimale du message
Vincent Vega
Déjà mentionné sur: superuser.com/a/125390/128124
Ciro Santilli 中心 六四 事件
0

Vous pouvez utiliser l' outil gvimdiff inclus dans le paquet vim-gui-common

sudo apt-get update

sudo apt-get install vim-gui-common

Ensuite, vous pouvez comparer 2 fichiers hexadécimaux en utilisant les commandes suivantes:

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

C'est tout. J'espère que l'aide!

fou
la source
0

L'outil d'analyse de micrologiciel a binwalkégalement cela comme fonctionnalité via son option de ligne de commande -W/--hexdump qui offre des options telles que d'afficher uniquement les différents octets:

    -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

Dans l'exemple de OP en faisant binwalk -W file1.bin file2.bin:

binwalk -W fichier1.bin fichier2.bin

phk
la source
-2

Le produit open source sous Linux (et tout le reste) est Radare, qui fournit radiff2explicitement cet objectif. J'ai voté pour fermer ceci parce que moi - même et d'autres avons la même question, dans la question que vous posez

pour chaque octet différent

C'est fou cependant. Parce que comme demandé, si vous insérez un octet au premier octet du fichier, vous constaterez que chaque octet suivant est différent et que le diff répète le fichier entier, avec une différence réelle d'un octet.

Un peu plus pratique est radiff -O. Le -Opour "" Faire la différence de code avec tous les octets au lieu des octets de code d'opération fixes ""

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

Comme IDA Pro, Radare est un outil principal pour l’analyse binaire. Vous pouvez également afficher les différences delta avec -d, ou afficher les octets désassemblés au lieu d’hex -D.

Si vous posez ce genre de questions, consultez

Evan Carroll
la source