Wie vergleiche ich Binärdateien in Linux?
Ich muss zwei Binärdateien vergleichen und die Ausgabe in der Form erhalten:
Für jedes andere Byte. Wenn also file1.bin
00 90 00 11
In binärer Form und file2.bin
ist
00 91 00 10
Ich möchte so etwas wie
00000001 90 91
00000003 11 10
Gibt es eine Möglichkeit, dies unter Linux zu tun? Ich kenne cmp -l
aber es verwendet ein Dezimalsystem für Offsets und Oktal für Bytes, die ich vermeiden möchte.
16 answers
Dadurch werden Offset und Bytes in Hex gedruckt:
cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'
Oder tun Sie $1-1
, damit der erste gedruckte Offset bei 0 beginnt.
cmp -l file1.bin file2.bin | gawk '{printf "%08X %02X %02X\n", $1-1, strtonum(0$2), strtonum(0$3)}'
Leider ist strtonum()
spezifisch für GAWK, daher müssen Sie für andere Versionen von awk-z. B. mawk-eine Oktal-zu-Dezimal-Konvertierungsfunktion verwenden. Zum Beispiel
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)}'
Zur Lesbarkeit ausgebrochen:
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)
}'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2016-12-22 15:55:36
Als ~quack betonte:
% xxd b1 > b1.hex
% xxd b2 > b2.hex
Und dann
% diff b1.hex b2.hex
Oder
% vimdiff b1.hex b2.hex
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2018-02-15 13:37:35
diff
+ xxd
Versuchen Sie es mit diff
in der folgenden Kombination von zsh / Bash-Prozesssubstitution:
diff -y <(xxd foo1.bin) <(xxd foo2.bin)
Wobei:
-
-y
zeigt Ihnen Unterschiede nebeneinander (optional). -
xxd
ist ein CLI-Tool zum Erstellen einer Hexdump-Ausgabe der Binärdatei. - Fügen Sie
-W200
zudiff
für eine breitere Ausgabe (von 200 Zeichen pro Zeile) hinzu. - Verwenden Sie für Farben
colordiff
wie unten gezeigt.
colordiff
+ xxd
Wenn Sie colordiff
haben, kann es colorize diff
Ausgabe, zB:
colordiff -y <(xxd foo1.bin) <(xxd foo2.bin)
Andernfalls installieren Sie über: sudo apt-get install colordiff
.
Beispielausgabe:
vimdiff
+ xxd
Sie können auch vimdiff
, zB
vimdiff <(xxd foo1.bin) <(xxd foo2.bin)
Hinweise:
- wenn Dateien zu groß sind, fügen Sie Limit (zB
-l1000
) für jedesxxd
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2019-06-13 15:33:33
Es gibt ein Tool namens DHEX, das den Job erledigen kann, und es gibt ein anderes Tool namens VBinDiff.
Versuchen Sie für einen strikten Befehlszeilenansatz jojodiff.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2019-06-24 11:00:02
Methode, die für Byte-Addition / - löschung funktioniert
diff <(od -An -tx1 -w1 -v file1) \
<(od -An -tx1 -w1 -v file2)
Generieren Sie einen Testfall mit einer einzigen Entfernung von 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
Ausgabe:
64d63
< 40
Wenn Sie auch die ASCII-Version des Zeichens sehen möchten:
bdiff() (
f() (
od -An -tx1c -w1 -v "$1" | paste -d '' - -
)
diff <(f "$1") <(f "$2")
)
bdiff file1 file2
Ausgabe:
64d63
< 40 @
Getestet unter Ubuntu 16.04.
Ich bevorzuge od
gegenüber xxd
weil:
- es ist POSIX,
xxd
ist nicht (kommt mit Vim) - hat die
-An
, um die Adresse zu entfernen Spalte ohneawk
.
Befehl erklärung:
-
-An
entfernt die Adressspalte. Dies ist wichtig, da sich sonst alle Zeilen nach einer Byte-Addition / - entfernung unterscheiden würden. -
-w1
setzt ein Byte pro Zeile, damit diff es verbrauchen kann. Es ist wichtig, ein Byte pro Zeile zu haben, da sonst jede Zeile nach einem Löschen nicht mehr in der Phase wäre und sich unterscheidet. Leider ist dies nicht POSIX, sondern in GNU vorhanden. -
-tx1
ist die Darstellung, die Sie wollen, ändern Sie auf einen beliebigen Wert, solange Sie 1 Byte pro Zeile behalten. -
-v
verhindert Sternchenwiederholungen*
, die den Diff stören könnten -
paste -d '' - -
verbindet alle zwei Zeilen. Wir brauchen es, weil Hex und ASCII in separate benachbarte Zeilen gehen. Entnommen aus: https://stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next - wir verwenden Klammern
()
, umbdiff
anstelle von{}
zu definieren, um den Umfang des innere Funktionf
, siehe auch: https://stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bash
Siehe auch:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2017-11-09 12:30:55
Kurze Antwort
vimdiff <(xxd -c1 -p first.bin) <(xxd -c1 -p second.bin)
Wenn Hexdumps und Text diff zum Vergleichen von Binärdateien verwendet werden, insbesondere xxd
, werden die Hinzufügungen und Entfernungen von Bytes zu Verschiebungen in der Adressierung, die das Erkennen erschweren könnten. Diese Methode weist xxd an, keine Adressen auszugeben und nur ein Byte pro Zeile auszugeben, was wiederum genau anzeigt, welche Bytes geändert, hinzugefügt oder entfernt wurden. Sie können die Adressen später finden, indem Sie in einem "normaleren" Hexdump (Ausgabe von xxd first.bin
).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-04-22 12:10:51
Ich würde hexdump empfehlen, um Binärdateien in Textformat und kdiff3 für die DIFF-Anzeige zu speichern.
hexdump myfile1.bin > myfile1.hex
hexdump myfile2.bin > myfile2.hex
kdiff3 myfile1.hex myfile2.hex
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2013-06-12 07:46:34
Das hexdiff
ist ein Programm, das genau das tut, wonach Sie suchen.
Verwendung:
hexdiff file1 file2
Es zeigt das Hex (und 7-Bit ASCII) der beiden Dateien übereinander an, wobei Unterschiede hervorgehoben werden. Schauen Sie sich man hexdiff
an, damit sich die Befehle in der Datei bewegen können, und ein einfaches q
wird beendet.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-11-03 16:42:25
Es beantwortet die Frage möglicherweise nicht streng, aber ich verwende dies zum Verteilen von Binärdateien:
gvim -d <(xxd -c 1 ~/file1.bin | awk '{print $2, $3}') <(xxd -c 1 ~/file2.bin | awk '{print $2, $3}')
Es druckt beide Dateien als hex und ASCII Werte, ein Byte pro Zeile, und verwendet dann die Diff-Funktion von Vim, um sie visuell zu rendern.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2014-06-08 09:02:36
Das Firmware-Analyse-Tool binwalk
hat dies auch als Feature durch seine -W
/--hexdump
Befehlszeilenoption, die Optionen bietet, um nur die unterschiedlichen Bytes anzuzeigen:
-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
Im Beispiel von OP, wenn binwalk -W file1.bin file2.bin
:
Fügen Sie | less -r
zum Paging hinzu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-04-30 08:26:04
Dhex http://www.dettus.net/dhex/
DHEX ist mehr als nur ein weiterer Hex-Editor: Er enthält einen Diff-Modus, mit dem zwei Binärdateien einfach und bequem verglichen werden können. Da es auf ncurses basiert und thematisierbar ist, kann es auf einer beliebigen Anzahl von Systemen und Szenarien ausgeführt werden. Mit der Verwendung von Suchprotokollen ist es möglich, Änderungen in verschiedenen Iterationen von Dateien einfach zu verfolgen.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2017-08-18 11:25:28
Unten ist ein Perl-Skript, colorbindiff, das ein binäres Diff ausführt, wobei Byte-Änderungen berücksichtigt werden aber auch Byte-Ergänzungen / - löschungen (viele der hier vorgeschlagenen Lösungen behandeln nur Byte-Änderungen), wie in einem Textdiff. Es ist auch auf GitHub verfügbar.
Es zeigt Ergebnisse neben Farben an, und dies erleichtert die Analyse erheblich.
Colorbindiff Ausgabe snapshot -
Um es zu benutzen:
perl colorbindiff.pl FILE1 FILE2
Das Skript:
#!/usr/bin/perl
#########################################################################
#
# VBINDIFF.PL : A side-by-side visual diff for binary files.
# Consult usage subroutine below for help.
#
# Copyright (C) 2020 Jerome Lelasseux [email protected]
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
#########################################################################
use warnings;
use strict;
use Term::ANSIColor qw(colorstrip colored);
use Getopt::Long qw(GetOptions);
use File::Temp qw(tempfile);
use constant BLANK => "..";
use constant BUFSIZE => 64 * 1024; # 64kB
sub usage
{
print "USAGE: $0 [OPTIONS] FILE1 FILE2\n";
print "Show a side-by-side binary comparison of FILE1 and FILE2. Show byte modifications but also additions and deletions, whatever the number of changed bytes. Rely on the 'diff' external command such as found on Linux or Cygwin. The algorithm is not suited for large and very different files.\n";
print "Author: Jerome Lelasseux \@2021\n";
print "OPTIONS: \n";
print " --cols=N : display N columns of bytes.diff Default is 16.\n";
print " --no-color : don't colorize output. Needed if you view the output in an editor.\n";
print " --no-marker : don't use the change markers (+ for addition, - for deletion, * for modified).\n";
print " --no-ascii : don't show the ascii columns.\n";
print " --only-changes : only display lines with changes.\n";
exit;
}
# Command line arguments
my $maxCols = 16;
my $noColor = 0;
my $noMarker = 0;
my $noAscii = 0;
my $noCommon = 0;
GetOptions(
'cols=i' => \$maxCols,
'no-ascii' => \$noAscii,
'no-color' => \$noColor,
'no-marker' => \$noMarker,
'only-changes' => \$noCommon
) or usage();
usage() unless ($#ARGV == 1);
my ($file1, $file2) = (@ARGV);
# Convert input files into hex lists
my $fileHex1 = createHexListFile($file1);
my $fileHex2 = createHexListFile($file2);
# Process diff -y output to get an easy-to-read side-by-side view
my $colIndex = 0;
my $oldPtr = 0;
my $newPtr = 0;
my $oldLineBuffer = sprintf("0x%04X ", 0);
my $newLineBuffer = sprintf("0x%04X ", 0);
my $oldCharBuffer;
my $newCharBuffer;
my $isDeleting = 0;
my $isAdding = 0;
my $isUnchangedLine = 1;
open(my $fh, '-|', qq(diff -y $fileHex1 $fileHex2)) or die $!;
while (<$fh>)
{
# Parse line by line the output of the 'diff -y' on the 2 hex list files.
# We expect:
# "xx | yy" for a modified byte
# " > yy" for an added byte
# "xx <" for a deleted byte
# "xx xx" for identicial bytes
my ($oldByte, $newByte);
my ($oldChar, $newChar);
if (/\|/)
{
# Changed
if ($isDeleting || $isAdding)
{
printLine($colIndex);
}
$isAdding = 0;
$isDeleting = 0;
$isUnchangedLine = 0;
/([a-fA-F0-9]+)([^a-fA-F0-9]+)([a-fA-F0-9]+)/;
$oldByte = formatByte($1, 3);
$oldChar = toPrintableChar($1, 3);
$newByte = formatByte($3, 3);
$newChar = toPrintableChar($3, 3);
$oldPtr++;
$newPtr++;
}
elsif (/</)
{
# Deleted in new
if ($isAdding)
{
printLine($colIndex);
}
$isAdding = 0;
$isDeleting = 1;
$isUnchangedLine = 0;
/([a-fA-F0-9]+)/;
$oldByte=formatByte($1, 2);
$oldChar=toPrintableChar($1, 2);
$newByte=formatByte(BLANK, 2);
$newChar=colorize(".", 2);
$oldPtr++;
}
elsif (/>/)
{
# Added in new
if ($isDeleting)
{
printLine($colIndex);
}
$isAdding = 1;
$isDeleting = 0;
$isUnchangedLine = 0;
/([a-fA-F0-9]+)/;
$oldByte=formatByte(BLANK, 1);
$oldChar=colorize(".", 1);
$newByte=formatByte($1, 1);
$newChar=toPrintableChar($1, 1);
$newPtr++;
}
else
{
# Unchanged
if ($isDeleting || $isAdding)
{
printLine($colIndex);
}
$isDeleting = 0;
$isAdding = 0;
/([a-fA-F0-9]+)([^a-fA-F0-9]+)([a-fA-F0-9]+)/;
$oldByte=formatByte($1, 0);
$oldChar=toPrintableChar($1, 0);
$newByte=formatByte($3, 0);
$newChar=toPrintableChar($3, 0);
$oldPtr++;
$newPtr++;
}
# Append the bytes to the old and new buffers
$oldLineBuffer .= $oldByte;
$oldCharBuffer .= $oldChar;
$newLineBuffer .= $newByte;
$newCharBuffer .= $newChar;
$colIndex++;
if ($colIndex == $maxCols)
{
printLine();
}
}
printLine($colIndex); # Possible remaining line
#================================================================
# subroutines
#================================================================
# $1 a string representing a data byte
# $2 0=unchanged, 1=added, 2=deleted, 3=changed
# return the formatted string (color/maker)
sub formatByte
{
my ($byte, $type) = @_;
my $res;
if (!$noMarker)
{
if ($type == 0 || $byte eq BLANK) { $res = " " . $byte; } # Unchanged or blank
elsif ($type == 1) { $res = " +" . $byte; } # Added
elsif ($type == 2) { $res = " -" . $byte; } # Deleted
elsif ($type == 3) { $res = " *" . $byte; } # Changed
else { die "Error"; }
} else
{
$res = " " . $byte;
}
$res = colorize($res, $type);
return $res;
}
# $1 a string
# $2 0=unchanged, 1=added, 2=deleted, 3=changed
# return the colorized string according to $2
sub colorize
{
my ($res, $type) = @_;
if (!$noColor)
{
if ($type == 0) { } # Unchanged
elsif ($type == 1) { $res = colored($res, 'bright_green'); } # Added
elsif ($type == 2) { $res = colored($res, 'bright_red'); } # Deleted
elsif ($type == 3) { $res = colored($res, 'bright_cyan'); } # Changed
else { die "Error"; }
}
return $res;
}
# Print the buffered line
sub printLine
{
if (length($oldLineBuffer) <=10)
{
return; # No data to display
}
if (!$isUnchangedLine)
{
# Colorize and add a marker to the address of each line if some bytes are changed/added/deleted
my $prefix = substr($oldLineBuffer, 0, 6) . ($noMarker ? " " : "*");
$prefix = colored($prefix, 'magenta') unless $noColor;
$oldLineBuffer =~ s/^......./$prefix/;
$prefix = substr($newLineBuffer, 0, 6) . ($noMarker ? " " : "*");
$prefix = colored($prefix, 'magenta') unless $noColor;
$newLineBuffer =~ s/^......./$prefix/;
}
my $oldCBuf = $noAscii ? "" : $oldCharBuffer;
my $newCBuf = $noAscii ? "" : $newCharBuffer;
my $spacerChars = $noAscii ? "" : (" " x ($maxCols - $colIndex));
my $spacerData = ($noMarker ? " " : " ") x ($maxCols - $colIndex);
if (!($noCommon && $isUnchangedLine))
{
print "${oldLineBuffer}${spacerData} ${oldCBuf}${spacerChars} ${newLineBuffer}${spacerData} ${newCBuf}\n";
}
# Reset buffers and counters
$oldLineBuffer = sprintf("0x%04X ", $oldPtr);
$newLineBuffer = sprintf("0x%04X ", $newPtr);
$oldCharBuffer = "";
$newCharBuffer = "";
$colIndex = 0;
$isUnchangedLine = 1;
}
# Convert a hex byte string into a printable char, or '.'.
# $1 = hex str such as A0
# $2 0=unchanged, 1=added, 2=deleted, 3=changed
# Return the corresponding char, possibly colorized
sub toPrintableChar
{
my ($hexByte, $type) = @_;
my $char = chr(hex($hexByte));
$char = ($char =~ /[[:print:]]/) ? $char : ".";
return colorize($char, $type);
}
# Convert file $1 into a text file with 1 hex byte per line.
# $1=input file name
# Return the output file name
sub createHexListFile
{
my ($inFileName) = @_;
my $buffer;
my $in_fh;
open($in_fh, "<:raw", $inFileName) || die "$0: cannot open $inFileName for reading: $!";
my ($out_fh, $filename) = tempfile();
while (my $nbReadBytes = read($in_fh, $buffer, BUFSIZE))
{
my @hexBytes = unpack("H2" x $nbReadBytes, $buffer);
foreach my $hexByte (@hexBytes)
{
print $out_fh "$hexByte\n" || die "couldn't write to $out_fh: $!";
}
}
close($in_fh);
return $filename;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-05-23 12:34:54
Sie können die gvimdiff werkzeug, das im Paket vim-gui-common
Sudo apt-get update
Sudo apt-get install vim-gui-common
Dann können Sie zwei Hexadezimaldateien mit den folgenden Befehlen vergleichen:
ubuntu> gvimdiff <hex-file1> <hex-file2>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-06-12 13:48:39
Ich habe ein einfaches Skript geschrieben, um eine Binärdatei zu diff. Es wird der erste verschiedene Chunk (40 Bytes) und Offset gedruckt:
Https://gist.github.com/guyskk/98621a9785bd88cf2b4e804978950122
$ bindiff file1 file2
8880> 442408E868330300488D05825337004889042448C744240802000000E84F330300E88A2A0300488B
^^^^^^^^^ ^^
442408E868330300E59388E59388004889042448C744240802000000E84F330300E88A2A0300488B
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-05-23 12:35:03
Https://security.googleblog.com/2016/03/bindiff-now-available-for-free.html
BinDiff ist ein großartiges UI-Tool zum Vergleichen von Binärdateien, die kürzlich Open Source wurden.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2016-03-23 20:18:41
Das Open-Source-Produkt unter Linux (und allem anderen) ist Radare, das Folgendes bietet radiff2
explizit für diesen Zweck.
für jedes andere Byte
Das ist aber verrückt. Denn wie gefragt, wenn Sie ein Byte am ersten Byte in die Datei einfügen, würden Sie feststellen, dass jedes nachfolgende Byte anders ist und der Diff die gesamte Datei für einen tatsächlichen Unterschied von einem Byte wiederholt.
Etwas praktischer ist radiff -O
. Das -O
für ""Mach code diffing mit allen Byte anstatt nur die festen opcode-bytes""
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
Wie IDA Pro ist Radare ein primäres Werkzeug für die binäre Analyse, und Sie können auch Delta-Diffing mit -d
anzeigen oder die zerlegten Bytes anstelle von Hex mit -D
anzeigen.
Siehe auch:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-05-23 12:38:03