ドキュメントなしでレガシーバイナリデータファイルをどのように解釈できますか?

StackOverflow https://stackoverflow.com/questions/1801978

  •  05-07-2019
  •  | 
  •  

質問

データは、多くの場合、ドキュメントがほとんどまたはまったくないプログラム固有のバイナリファイルに保存されます。私たちの分野の典型的な例は、機器からのデータですが、問題は一般的なものだと思います。データの理解と解釈を試みるための方法は何ですか?

境界を設定するには。ファイルは暗号化されておらず、DRMはありません。ファイルのタイプと形式はプログラムの作成者に固有です(つまり、*。tarなどのIDが失われた「標準ファイル」ではありません)。 (おそらく)意図的な難読化はありませんが、スペースを節約するためのアマチュアの努力があるかもしれません。データが何であるかについての一般的な知識があり、フィールドと配列の一部ではあるがおそらくすべてではないことを認識していると想定できます。

データの大部分は数値、スカラー、および配列(おそらく1次元と2次元で、場合によっては不規則または三角形)であると想定します。また、いくつかの文字列、おそらく人の名前、サイト、日付、そしておそらくいくつかのキーワードがあります。バイナリファイルを読み取るプログラムにはコードがありますが、ソースまたはアセンブラへのアクセス権はありません。例として、VAX Fortranプログラムまたは初期のUnixまたはWindowsによってOLEオブジェクトとして作成された可能性があります。数値はビッグエンディアンまたはリトルエンディアン(最初は不明)かもしれませんが、おそらく一貫しています。我々 異なるマシン(たとえば、Cray)に異なるバージョンがある場合があります。

適度に大きいファイルのコーパスがあると仮定できます-数百、たとえば。

2つのシナリオを想定できます:

  1. さまざまな入力でプログラムを再実行して、実験を行うことができます。
  2. プログラムを再実行することはできません-一連のドキュメントが固定されています。これは、未知の言語(たとえば、Linear B)で履歴文書をデコードするのとやや似ています。

部分的な解決策は受け入れられる場合があります。つまり、現在は誰も理解していないフィールドもありますが、他のほとんどは解釈可能です。

オープンソースのアプローチにのみ興味があります。

更新関連するSOの質問があります(互換性を目的としてバイナリファイル形式をリバースエンジニアリングする方法)。ただし、強調は多少異なります。 更新 @brianeggeからアドレス(1)への巧妙な提案。 truss (またはLinuxの場合は strace )を使用して、プログラム内のすべてのwrite()および同様の呼び出しをダンプします。これにより、少なくともディスクに書き込まれたレコードのコレクションが許可されます。

役に立ちましたか?

解決

これは興味深い質問です。その答えは、バイナリ形式のリバースエンジニアリングは習熟したスキルであると思いますが、役立つツールがあります。

1つのツールは WinOLS です。これは、車両エンジン管理コンピューターのバイナリイメージ(主にルックアップテーブルの数値データ)を解釈および編集するために設計されています。さまざまなエンディアン形式(PDPではないが)をサポートし、さまざまな幅とオフセットでデータを表示し、配列領域(マップ)を定義し、あらゆる種類のスケーリングおよびオフセットオプションを使用して2Dまたは3Dで視覚化します。また、ヒューリスティック/統計的な自動マップファインダがあり、これが役立つ場合があります。

これは商用ツールですが、無料のデモでは、バイナリへの変更を保存し、不要なエンジン管理機能を使用する以外のすべてを実行できます。あなたはオープンソースのソリューションにのみ興味があると言いましたが、これはStackoverflowであり、他の誰かはそれほどうるさくないかもしれません。

他のヒント

すべてのファイルにはヘッダーがあります。そこから始めて、2つのファイルの類似点を確認し、一般的な「署名」を削除します。違いを処理します。レコード数、エクスポート日などをマークする必要があります。

2つのヘッダー間の共通部分は一般的な署名と見なされる可能性があり、無視できると思います

トラス 、システムコールを監視するだけで、おそらく良いアイデアが得られるでしょう。また、プログラムがファイルをmmapし、メモリから直接コピーする可能性もありますが、それはあまり一般的ではありません。

$ truss -t write echo foo
foowrite(1, " f o o", 3)                                = 3
write(1, "\n", 1)                               = 1

バイナリを見るのも理にかなっているかもしれません。 Unixシステムでは、 objdump を使用してバイナリのレイアウトを表示できます。これは、コードおよびデータセクションを指します。その後、16進エディタでバイナリを開き、特定のオフセットに移動できます。 Solarisバイナリファイルのヒントに興味があるかもしれません。

  • 類似性を探すために2つ以上のファイルを比較します。これは、ヘッダーブロックとファイルのさまざまなセクションを識別するのに役立ちます。

  • エンディアンネスは通常かなり簡単に解決できます。重要度の高いバイトは、重要度の低いバイトよりも頻繁にゼロになる傾向があるため、「00 78」のようなパターンが表示される場合、または「78 00」どのバイトがmsbであるかを適切に推測できます。ただし、これは、前のデータが何であるかを(おおよそ)解決した場合にのみ役立つので、データがどのように整列されているかがわかります。

  • 簡単に識別できるデータを探します-文字列は簡単に見つけることができるため、最初に開始する場所です。これらは通常、関連データの近くに埋め込まれ、ヘッダーなどの標準項目として使用されるため、手がかりを提供します。文字列がユニコードの場合、通常、エンディアンを識別するのに役立つテキストの文字がゼロバイトで区切られて表示されます、およびデータ内のそのポイントでのデータの配置。

  • 一般的な形式のアプローチ(IFFなど)は、小さなヘッダー(たとえば、2バイトまたは4バイトのID、ブロックの2バイトまたは4バイトのサイズ、次にブロック)。一般に、人々は意味のある(彼らにとって)チャンクIDを使用するため、簡単に見つけることができます-タグのように見えるものを見つけたら、次のデータをチェックして、長さのように見えるかどうかを確認します別のヘッダーがあるように見えるかどうかを確認します)。そのような形式を識別できる場合は、「1つの大きなファイル」を分割します。問題を「多数の小さなファイル」に分割それがはるかに簡単になる問題。 (ただし、コンパクトにするために多くのデバイスデータが「最適化」される傾向があり、その場合、プログラマーは便利な拡張可能なフォーマットを捨ててすべてを詰め込み、ビットを詰めて一般的に物事をはるかに難しくします)

  • 既知の値を探します。デバイスに「温度:40」と表示されている場合その値がファイルに直接保存されている可能性があります。 (スケーリング係数または固定小数点値を使用することも一般的であるため、40は(たとえば)40 * 10 = 400または40 * 256 = 10240として表されます)

  • デバイスを十分に制御できる場合:簡単なファイルを作成します。達成しようとしているのは、検査する必要のあるデータを最小限に抑えるためにデバイスから取り出すことができる最小のファイルです。次に、ファイルの変更を引き起こすデバイスで変更を行います-変更の数を最小限に抑えるようにして-ファイルを再度取得します。ファイル形式が「開く」場合(圧縮または暗号化されていない)、変更されたバイトを識別できるはずです。

  • "ロード"できる場合ファイルをデバイスに戻すと、独自のファイルを作成できる場合があります。1つの値を変更するだけで、デバイスの動作の変化に気付くことができるかどうかを確認できます。単純な値にヒットした場合、これはうまく機能しますが、多くの場合、ファイル形式を破るだけで、デバイスはデータをまったく読み取れなくなることがあります。

パターンを解決したり、別のエンディアンを試すことができる魔法のユーティリティがあることを望んでいました。しかし、そうではないようです!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top