Linuxのバイナリファイルを比較するにはどうすればよいですか?


304

2つのバイナリファイルを比較し、次の形式で出力を取得する必要があります。

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

異なるバイトごとに。もしそうfile1.binです

  00 90 00 11

バイナリ形式でfile2.binあり

  00 91 00 10

次のようなものを取得したい

  00000001 90 91
  00000003 11 10

Linuxでこれを行う方法はありますか?私は知ってcmp -lいますが、オフセットには10​​進法を使用し、回避したいバイトには8進法を使用します。


9
基本的に「バイナリ差分」を探しています。私はいくつかのreeeally醜いコマンドラインワンライナーを想像することができますod...
いんちきキホーテ

2
@quack quixote:ワンライナーのいところは何ですか?;)
ボビー

xdelta.orgは非常にうまく機能します。おそらくそれを見てみる価値があるでしょう。
thatjuan

(あなたはユーザーではないので)この質問に答えることができないので、私は終了することを投票しています。ここで明示的に要求されているバイナリdiffはまったく役に立ちません。ファイルの先頭に1バイトを挿入すると、すべてのバイトが異なるものとしてマークされるはずです。それを知らずに、これは単に曖昧すぎます。
エヴァンキャロル

2
@EvanCarrollもし質問がトピックから外れていると思うなら、なぜあなたはそれに答えているのですか?
DavidPostill

回答:


174

これにより、オフセットとバイトが16進数で出力されます。

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

または$1-1、最初の印刷オフセットを0から開始します。

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

残念ながら、これstrtonum()はGAWKに固有であるため、awkの他のバージョン(例:mawk)では、8進数から10進数への変換関数を使用する必要があります。例えば、

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

読みやすくするために分割:

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:GAWKにstrtonum固有です。Ubuntuは以前はGAWKをデフォルトとして使用していましたが、ある時点でに切り替えたと思いますmawk。いずれの場合でも、GAWKをインストールしてデフォルトに設定できます(も参照man update-alternatives)。必要のないソリューションについては、更新された回答を参照してくださいstrtonum
デニスウィリアムソン

両方のファイルのsha256sumを単純に比較してみませんか?
ロドリゴ

1
@Rodrigo:それと他のさまざまな方法は、ファイルが異なるかどうかを示すだけです。私の答えは、違いが何であるかを実際に示すというOPの要件を満たしています。
デニスウィリアムソン

もちろん!申し訳ありませんが、私は自分の問題をとても心配していたため、OPをほとんど読みませんでした。ありがとうございました。
ロドリゴ

166

〜いんちきは指摘しました:

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

その後

 % diff b1.hex b2.hex

または

 % vimdiff b1.hex b2.hex

70
Bashの場合:diff <(xxd b1) <(xxd b2)しかし、この(またはあなたの)出力形式は、OPが要求したもののどこにもありません。
デニスウィリアムソン

6
vimdiffでそれは2つの「ファイル」は異なるラインでバイトを色付けします、です
あきら

なんでそんなこと考えなかったの?そして、私も過去にこのテクニックを使用したことがあると確信しています。
njd

1
これは私にとってはうまくいきました(opendiffOS Xではなくvimdiff)。デフォルトのビューでxxdは、差分エンジンがバイト単位で比較されます。単純な(生の)16進数では、単に列に合わせてfolddiff比較しているファイル内のランダムなものを折りたたんだりグループ化しようとします。
natevw 14年

1
このコマンドは、後続のすべての行の位置がずれており、変更されたと見なされるため、バイト追加の削除には適していませんdiff。解決策は、John Lawrence Aspden私が提案したように、1行に1バイトを入れてアドレス列を削除することです
Ciro Santilli新疆改造中心法轮功六四事件

98

diff + xxd

diff次のzsh / bashプロセス置換の組み合わせを試してください。

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

どこ:

  • -y 違いを並べて表示します(オプション)。
  • xxd バイナリファイルのhexdump出力を作成するCLIツールです。
  • より広い出力(1行に200文字)を追加-W200diffます。
  • 色についてはcolordiff、次のように使用します。

colordiff + xxd

を使用している場合colordiffdiff出力を色付けできます。例:

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

それ以外の場合:経由でインストールしますsudo apt-get install colordiff

サンプル出力:

ターミナルで出力されるバイナリファイル-diff -y <(xxd foo1.bin)<(xxd foo2.bin)|  colordiff

vimdiff + xxd

を使用することもできますvimdiff、例えば

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

ヒント:

  • ファイルが大きすぎる場合は-l1000、それぞれに制限(たとえば)を追加しますxxd

11
コマンドはとして簡略化できますcolordiff -y <(xxd foo1.bin) <(xxd foo2.bin)
ゴーレム

3
あなたはcolordiffを持っていない場合、これは色なしで同じことを行います:diff -y <(xxd foo1.bin) <(xxd foo2.bin)
ロック・リー

5
両方のファイルが実際に同じであるかどうかだけを知りたい場合は、-qor --briefスイッチを使用して、ファイルが異なる場合にのみ出力を表示できます。
ステファンヴァンデンアクカー

1
xxddiffこのための関数を作成しますxxddiff() ( f() ( xxd "$1" ; ); diff -y <(f "$1") <(f "$2") | colordiff; )
。– rubo77

2
すばらしいです!それでも、diff -u <(xxd tinga.tgz) <(xxd dec.out.tinga.tgz) | vim - 良い仕事をします
リバマー

56

ツールがありますDHEX仕事をすること、そして呼ばれる別のツールがありますVBinDiffが

厳密なコマンドラインアプローチについては、jojodiffを試してください


8
DHEXは素晴らしいです。バイナリを比較するのがやりたいことです。2つのファイルをフィードすると、比較ビューが表示され、違いが強調表示され、次の違いに簡単に移動できます。また、ワイドスクリーンモニターでは非常に便利な大型の端末でも動作します。
マーチン

7
VBinDiffが好きです。DHEXはアイドリング時でもCPUを使用しているため、常に再描画するか何かと思います。ただし、VBinDiffはワイドターミナルでは動作しません。しかし、1行あたり16バイト以上あるため、とにかく幅の広い端末ではアドレスが奇妙になります。
ヤヌストロエルセン

1
vbindiffを使用すると、ファイルthxを実際に編集できます。
アクエリアスパワー14

2
@DanielBeauyatの圧縮ファイルは、最初の異なるバイトに遭遇すると完全に異なります。出力は有用ではない可能性があります。
マークランサム

2
@ 1111161171159459134 jdiffは、jdiffによって検出された差分を同期およびパッチするプログラムの「スイート」の一部です。しかし、Mark Ransomが言ったように、それは一般に圧縮ファイルでは賢明ではありません。例外は「同期可能な」圧縮形式(gzip --rsyncableで生成される形式など)です。この形式では、非圧縮ファイルのわずかな違いが圧縮ファイルに限定的な影響を与えるはずです。
hmijail

27

バイトの追加/削除に機能するメソッド

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

バイト64を1回削除してテストケースを生成します。

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

出力:

64d63
<  40

文字のASCIIバージョンも表示する場合:

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

bdiff file1 file2

出力:

64d63
<   40   @

Ubuntu 16.04でテスト済み。

私が好むod超えるxxdので:

  • それはPOSIXであるxxd(Vimのが付属しています)されていません
  • 持ってい-Anなくてアドレス欄を削除しますawk

コマンドの説明:

  • -Anアドレス列を削除します。そうしないと、バイトの追加/削除後にすべての行が異なることになります。
  • -w1diffがそれを消費できるように、1行に1バイトを入れます。行ごとに1バイトを使用することが重要です。そうしないと、削除後のすべての行が位相がずれて異なってしまいます。残念ながら、これはPOSIXではなく、GNUに存在します。
  • -tx1 行ごとに1バイトを保持する限り、任意の可能な値に変更したい表現です。
  • -v*diffに干渉する可能性のあるアスタリスクの繰り返し略語を防ぎます
  • paste -d '' - -2行ごとに結合します。16進数とASCIIは別々の隣接する行に入るため、必要です。から取得:https : //stackoverflow.com/questions/8987257/concatenating-every-other-line-with-the-next
  • 内部関数のスコープを制限()するbdiff代わりに、かっこを使用して定義します。https//stackoverflow.com/questions/8426077/how-to-define-a-function-inside-another-function-in-bashも参照してください{}f

こちらもご覧ください:


13

簡潔な答え

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

hexdumpsとtext diffを使用してバイナリファイルを比較する場合、特にxxd、バイトの追加と削除はアドレス指定のシフトになり、見づらくなる可能性があります。このメソッドは、アドレスを出力せず、行ごとに1バイトのみを出力するようにxxdに指示します。これにより、変更、追加、または削除されたバイトが正確に示されます。後でアドレスを見つけるには、より「通常の」hexdump(の出力xxd first.bin)で興味深いバイトシーケンスを検索します。


(もちろん、。のdiff代わりに使用できますvimdiff。)
VasyaNovikov

11

バイナリファイルをテキスト形式にダンプするにはhexdumpを、差分表示にはkdiff3をお勧めします。

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

2
ここでもbash kdiff3 <(hexdump myfile1.bin) <(hexdump myfile2.bin)で、ファイルmyfile1.hexやを作成する必要はありませんmyfile2.hex
ハスター

5

hexdiffあなたが探している正確に何をするように設計されたプログラムです。

使用法:

hexdiff file1 file2

2つのファイルの16進(および7ビットASCII)が上下に表示され、相違点が強調表示されます。見てman hexdiffのコマンドは、ファイル内を移動するために、そしてシンプルにq終了します。


4
しかし、比較部分に関してはかなり悪い仕事をします。ファイルにいくつかのバイトを挿入すると、その後すべてのバイトが変更としてマークされます
-Murmel

hexdiffはUbuntu 16.4のapt-getでは利用できません
rubo77

1
@Murmelは同意しますが、それはここで尋ねられていることではありませんか?
エヴァンキャロル

@EvanCarroll tr​​ue。したがって、コメント(のみ)を残し、ダウン投票しませんでした
Murmel

私はまた、ミックダウン投票しなかったが、私はあなたに同意し、ここで答えsuperuser.com/a/1373977/11116この悪い質問は改質または閉鎖されます可能性が高いようなので。
エヴァンキャロル

3

それは厳密に質問に答えないかもしれませんが、私はこれをバイナリの差分に使用します:

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

両方のファイルを16進値とASCII値として1行に1バイトで出力し、Vimのdiff機能を使用して視覚的にレンダリングします。


0

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

DHEXは、単なる別の16進エディタではありません。2つのバイナリファイルを簡単かつ便利に比較するために使用できるdiffモードが含まれています。これはncursesに基づいており、テーマ設定可能であるため、任意の数のシステムおよびシナリオで実行できます。検索ログを利用することで、ファイルのさまざまな反復の変更を簡単に追跡できます。


SuperUserへようこそ!このソフトウェアはOPの問題を解決できるように見えますが、Stack Exchangeネットワークでは純粋な広告が強く嫌われています。このソフトウェアの編集者と提携している場合は、この事実を開示してください。そして、コマーシャルのように見えないように投稿を書き直してください。ありがとうございました。
Nathan.Eilisha Shiraini

私はdhexとは一切関係ありません。投稿の長さに制限があるため、著者の説明を投稿にコピーしました
ビンセントベガ


0

vim-gui-commonパッケージに含まれているgvimdiffツールを使用できます

sudo apt-get update

sudo apt-get install vim-gui-common

次に、次のコマンドを使用して2つのhexファイルを比較できます。

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

Thaのすべて。助けて欲しい!


0

ファームウェア分析ツールbinwalkには、異なるバイトのみを表示するなどのオプションを提供する-W/ --hexdumpコマンドラインオプションによる機能として、これもあります。

    -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

OPの例ではbinwalk -W file1.bin file2.bin

binwalk -W file1.bin file2.bin



-2

Linux(およびその他すべて)でオープンソース製品を使用するのはradiff2、この目的を明示的に提供するRadareです。私と他の人があなたが尋ねる質問で同じ質問をしているので、私はこれを閉じることに投票しました

異なるバイトごとに

しかし、それは非常識です。尋ねられたように、ファイルの最初のバイトに1バイトを挿入すると、後続のすべてのバイトが異なることがわかり、差分は実際の1バイトの差に対してファイル全体を繰り返すためです。

やや実用的ですradiff -O。これ-Oは、「固定オペコードバイトだけでなく、すべてのバイトでコードを差分化する」ためのものです

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

IDA Proと同様、Radarはバイナリ分析の主要ツールです。また、で差分差分を-d表示したり、で16進数の代わりに逆アセンブルされたバイトを表示したりすることもできます-D

この種の質問をしている場合は、チェックしてください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.