BinDiffソフトウェアの基本原則(および最適化とヒューリスティックに関するいくつかのこと)を知りたいです。誰かがそれについての素晴らしく教育的な説明を持っていますか?
BinDiffソフトウェアの基本原則(および最適化とヒューリスティックに関するいくつかのこと)を知りたいです。誰かがそれについての素晴らしく教育的な説明を持っていますか?
一般に、この記事の執筆時点での現在のバージョン(4.x)のBinDiffは、関数レベルで属性を照合することによって機能します。基本的に、マッチングは2つのフェーズに分けられます。最初の初期マッチングが生成され、ドリルダウンフェーズで絞り込まれます。
まず、BinDiffはに基づいて署名を関連付けます。各関数の次の属性:
このステップでは、各バイナリの署名のセットが提供されます。これは、最初の一致のセットを生成するために使用されます。 1対1の関係に従って、BinDiffは上記の特性に基づいてこれらの初期一致を選択します。
次のステップでは、各バイナリのコールグラフで一致を見つけようとします。検証された一致の場合、一致した関数から呼び出された関数は、さらに一致するイベントを見つけるために調べられます。このプロセスは、新しい一致が見つかる限り繰り返されます。
実際には、すべての関数が、最初の一致によって引き起こされた1対1の関係によって一致するわけではありません。戦略であるため、最初の一致が決定された後も、一致しない関数のリストがあります。ドリルダウンフェーズのアイデアは、一致が見つかるまで適用される複数の異なる関数一致戦略を持つことです。これらの戦略を適用する順序は重要です。BinDiffは、最初に、最も信頼性が高いと想定される戦略を試行します。一致するものが見つからなかった場合にのみ、次の戦略に進みます。これは、BinDiffが戦略を使い果たすまで、またはすべての関数が一致するまで繰り返されます。例としては、MDインデックス、関数名に基づく一致(つまり、インポート)、コールグラフエッジのMDインデックスなどがあります。
(免責事項:@ team zynamics / googleで作業しています。うまくいけば、私は何も台無しにしませんでした。さもないと、soerenが私を焼きます;-))
制御フローグラフの作成について少しだけ説明できますが、私の答えは完全ではありません。
BinDiffは静的タイプの実行フローを検出します。これは、コードを実行しているためだと思います。常に可能(たとえば、リング0ドライバーの場合)または合理的(マルウェア)であるとは限りません。実際には、指定されたファイルは分解されてから、基本ブロックに分割する必要があります(これらは、直接実行できるコードの断片ですが、この定義はまさにその場合です)。 jxx
のような命令がプログラムの制御フローを変更することは明らかです(たとえば、x86アーキテクチャを考慮して)。したがって、基本ブロックは通常、それらによって終了されます。コードをブロックに分割するこのプロセス自体は複雑な作業ではありません。より難しい部分は、ジャンプ先を決定することです。
たとえば、次のようなものです。
.. .. jz eax
したがって、この呼び出しがどこを指しているのかを自動静的分析で(簡単に)理解することはできません。些細なケースを「エミュレート」することもできますが、一般的に、その作業は非常に困難でイライラします。もう1つのオプションは、プログラムをトレースして、コードが実行されるパスを確認することです(手動で実行できます)。これらのブロックが見つかった場合、残っているのは人間が読めるグラフを作成することだけです。
とにかくあります。実行フローを変更できる方法の山(例外、別のスレッドによるホットパッチ、システム依存のイベントなど)。