1. 概要

この記事では、Linuxでバイナリファイルを比較するさまざまな方法について説明します。 データリカバリ、リバースエンジニアリング、およびその他のプログラミングの問題のためにさまざまなファイルを調査するときに、これが必要になる場合があります。

2. 問題文

この記事の問題を例示するために、最初に2つのバイナリファイルが必要です。 次に、これら2つのバイナリファイルを比較します。 を実行することでそれらを生成できますエコー 2つのオプションを持つコマンド。 フラグ-nは、末尾の改行の出力を防ぎます。 さらに、 -e フラグは、ファイルに必要なデータに16進値( \ xHH )を使用します:

$ echo -n -e \\x41\\x2e\\x42\\x2e\\x43\\x2e\\x44\\x2e > binary_file_1.bin
$ echo -n -e \\x41\\x2e\\x41\\x2e\\x42\\x2e\\x42\\x2e > binary_file_2.bin

バックスラッシュ自体をエスケープするには、ダブルバックスラッシュが必要です。

前のコマンドで、binary_file_1.binbinary_file_2.binの2つのバイナリファイルを作成しました。 最初の文字列には「ABCD」という文字列を格納し、2番目の文字列には「AABB」という文字列を格納しました。したがって、「BCD」と「ABB」の3文字が異なります。

この例では、ファイルの内容を知っていると、議論に役立ち、ツールの理解が容易になります。 しかし、実際には、内容は不明です。それは確かに私たちが発見したいものです!

3. ソリューション

一般に、問題は2つの部分に分けることができます。 最初の部分は、バイナリ情報を比較できる意味のあるものに変換することです。このために、odなどのツールを使用します。 xxd 、またはhexdump

問題の2番目の部分は、実際に以前に取得した情報を比較することです。 diffvimdiffなど、そのために使用できるツールは複数あります。 これらのツールを最初の3つの方法で示しますが、他の組み合わせで使用して、出力とフォーマットをさらにカスタマイズすることもできます。

提示された最後と4番目のソリューションは、このプロセスを逆にします。最初にファイルを比較し、次にバイナリ情報を文字列に変換します。 このソリューションのツールは、cmpおよびgawkです。

3.1. od with diff

odコマンド(8進ダンプを表す)を使用して、バイナリファイルを16進ファイルに変換できます。したがって、2つのファイルを次のように処理できます。

$ od -tx1 -v binary_file_1.bin > hexa_file_1.hd 
$ od -tx1 -v binary_file_2.bin > hexa_file_2.hd 

これで、バイナリファイルから作成された2つの16進ファイルができました。 -v フラグは、行抑制のアスタリスクの繰り返しを防ぎます( diff で問題が発生する可能性があります)。

odコマンドを-tx1フラグとともに使用して、16進数( x )のフォーマット -t で要求)を1つ()で指定します。 1 )ブロックあたりのバイト数。 その他の一般的なオプションは、 -tx2 で、ブロックごとに2バイトを16進形式で出力し、各ブロックのバイト順序を元に戻します。 -to1 は、ブロックごとに1バイトを8進形式で出力します。 。

バイトの追加や削除が予想される場合は、フォーマットを改善するために使用できる他の便利なフラグがあります。これらには、アドレス列を削除する -An 、および -w1 、これは1行に1バイトだけを配置します( diff を使用するときにフェーズを回避するために使用されます)。

16進ファイルを取得したら、次のようにdiffと比較できます。

$ diff hexa_file_1.od hexa_file_2.od
1c1
< 0000000 41 2e 42 2e 43 2e 44 2e
---
> 0000000 41 2e 41 2e 42 2e 42 2e

一方のコマンドからもう一方のコマンドへの入力リダイレクトを使用することで、新しいファイルを作成せずに両方のコマンドを実行できました。 これを説明し、 -tx2 フラグも表示するために、両方の機能が含まれている別の例があります。

$ diff <(od -tx2 -v binary_file_1.bin) <(od -tx2 -v binary_file_2.bin)
1c1
< 0000000 2e41 2e42 2e43 2e44
---
> 0000000 2e41 2e41 2e42 2e42

同じ情報を取得しますが、2バイトの各ブロックのバイトが反転していることに注意してください。

3.2. hexdump with diff

入力リダイレクトを使用した最後のスニペットに続いて、 diffとhexdumpを組み合わせて、バイナリファイルを比較できます

$ diff <(hexdump binary_file_1.bin) <(hexdump binary_file_2.bin)
1c1
< 0000000 2e41 2e42 2e43 2e44 
---
> 0000000 2e41 2e41 2e42 2e42 

結果は前のソリューションと同じであり、このアプローチの一貫性を示しています。

diff に共通するオプションの1つは、フラグ -y (または長いバージョン –side-by-side )で、両方のファイルを並べて表示します。 、複数行のファイルの理解を向上させる:

$ diff -y <(hexdump binary_file_1.bin) <(hexdump binary_file_2.bin)
0000000 2e41 2e42 2e43 2e44 | 0000000 2e41 2e41 2e42 2e42 
0000008                       0000008

3.3. xxd with diff

hexdump (または od )をxxdに置き換えることもできます。

$ diff -y <(xxd binary_file_1.bin) <(xxd binary_file_2.bin)
00000000: 412e 422e 432e 442e A.B.C.D. | 00000000: 412e 412e 422e 422e A.A.B.B.

これにより、以前とは異なる出力が生成されます。 ただし、検査により、2バイトのブロックの順序が逆になっていることを確認できます。 hexdump では、 2e-41 であり、xxdでは]、41-2eがあります。 これはエンディアンと呼ばれ、hexdumpとxxdの違いの1つです。

16進数の各文字列の後に、開始したテキストのASCII表現も取得していることがわかります。 これは、hexdump-Cフラグで実現できるものです。

diffvimdiffに置き換えて、ファイルをナビゲートし、比較を容易にすることができます(このソリューションおよび以前のすべてのソリューションで)。

$ vimdiff <(xxd binary_file_1.bin) <(xxd binary_file_2.bin)

3.4. cmp with gawk

この最後のソリューションでは、最初に2つのバイナリファイルをcmpツールでバイトごとに比較します。

$ cmp -l binary_file_1.bin binary_file_2.bin
3 102 101
5 103 102
7 104 102

予想どおり、2つのファイルが異なる場所は3つあります。 cmp の基本モードはファイルが異なるかどうかを示すだけなので、-lフラグを使用してファイルが異なる場所を表示しました。

ただし、出力はバイト情報であり、16進情報を処理する方が簡単です。 したがって、 gawk関数を使用して、2番目と3番目の列を16進数に変換できます。

$ cmp -l binary_file_1.bin binary_file_2.bin | gawk '{printf "%08X %02X %02X\n", , strtonum(0), strtonum(0)}'
00000003 42 41
00000005 43 42
00000007 44 42

3.5. どのソリューションを選択しますか?

これまで見てきたように、さまざまなソリューションの結果は同等であり、同様の結果を返します。 したがって、2つの主な要因に基づいて選択する必要があります。システムに必要なツールがインストールされているかどうかと、出力の目的のフォーマットです。

4. 結論

この記事では、2つのバイナリファイルの内容を比較するためのさまざまなソリューションについて説明しました。 例のケースを定義した後、コマンドとその出力を解釈する方法を含む4つのソリューションを示しました。