19

最初に、この質問をする理由について少し背景を説明します。

私は現在、厳しく規制された業界で働いているので、私たちのコードは公式のテストハウスによって非常に注意深く見守られています。これらのテストハウスは、コードをビルドして、毎回まったく同じである.exeまたは.dllを生成できることを期待しています(明らかにコードを変更する必要はありません!)。作成した実行可能ファイルのMD5とSHA1をチェックして、これを確認します。

この時点まで、私は主にC ++でコーディングしてきましたが、(いくつかのプロジェクト設定を微調整した後)プロジェクトを同じMD5/SHA1に一貫して再構築することができました。現在、プロジェクトでC#を使用していますが、再構築後にMD5を一致させるのに非常に苦労しています。ファイルのPEヘッダーに「タイムスタンプ」があり、それらが0にクリアされていることを認識しています。また、.exeのGUIDがあり、これも000000にクリアされていることも認識しています。 ...など。ただし、ファイルはまだ一致していません。

CFF Explorerを使用してPEヘッダーを表示および編集し、時刻と日付のスタンプを削除しています。バイナリ比較ツールを使用した後、.exeには異なる(両方とも非常に小さい)バイトのブロックが2つしかありません。

不整合なブロックの1つは、ASCIIでファイルのパスを詳細に示すバイナリコードの直前*Project*\obj\Release\xxx.pdbに表示されます。

編集:これは* .pdbファイルのGUIDであることがわかっていますが、エラーを発生させずに変更できるかどうかはまだわかりません!?

もう1つのブロックは、関数名のように見えるものの中央に表示されます。(典型的なセクション)AssemblyName.GetName.Version.get_Version.System.IO.Ports.SerialPort.Parity.Byte.<PrivateImplementationDetails>{

次に、別のコードブロック:

4A134ACE-D6A0-461B-A47C-3A4232D90816

に続く:

"} .ValueType .__ StaticArrayInitTypeSize=7。$$method0x60000ab-1.RuntimeFieldHandle.InitializeArray`...など。

どんなアイデアや提案も大歓迎です!

4

6 に答える 6

5

更新: Roslyn には/feature:deterministic再現可能なビルド用のコンパイラ フラグがあるようですが、まだ 100% は機能していません


PDB 生成を無効にすることで、デバッグ GUID を取り除くことができるはずです。そうでない場合は、GUID をゼロに設定しても問題ありません。デバッガーのみがそのセクションを参照します (アセンブリをデバッグすることはできなくなりますが、正常に動作するはずです)。

PrivateImplementationDetails はもう少し複雑です。これらは、特定の言語構造 (配列初期化子、文字列を使用した switch ステートメントなど) のためにコンパイラによって生成される内部ヘルパー クラスです。それらは内部でのみ使用されるため、クラス名は実際には重要ではないため、実行中の番号を割り当てることができます。

これを行うには、#Strings メタデータ ストリームを調べて、"<PrivateImplementationDetails>{GUID}" という形式のすべての文字列を "<PrivateImplementationDetails>{running number, padded to the same length to a GUID}" に置き換えます。

#Strings メタデータ ストリームは、UTF-8 でエンコードされ、\0 で区切られた、メタデータで使用される文字列の単なるリストです。そのため、#Strings ストリームが実行可能ファイル内のどこにあるかがわかれば、名前を見つけて置き換えるのは簡単です。

残念ながら、この情報を含む「メタデータ ストリーム ヘッダー」は、ファイル形式内に完全に埋もれています。NT オプション ヘッダーから開始し、CLI ランタイム ヘッダーへのポインターを見つけ、PE セクション テーブル (RVA ですが、ファイル内の位置が必要です) を使用してファイル位置に解決し、次に移動する必要があります。メタデータ ルートを取得し、ストリーム ヘッダーを読み取ります。

于 2009-09-23T21:30:31.853 に答える
2

PDB GUID の問題に関して、リリース ビルドのコンパイル時に PDB を生成しないように指定した場合、バイナリには PDB のファイル システム GUID が含まれていますか?

PDB生成を無効にするには:

  1. ソリューション エクスプローラーでプロジェクトを右クリックし、[プロパティ] を選択します。
  2. 左側のメニューから [ビルド] を選択します。
  3. [構成] の選択が [リリース] であることを確認します (デバッグ用の PDB は引き続き必要です)。
  4. 右下の [詳細設定] ボタンをクリックします。
  5. [出力/デバッグ情報] で [なし] を選択します。

コンソールからビルドしている場合は、/debug- を使用して同じ結果を得ることができます。

于 2009-09-22T17:02:55.450 に答える
2

これについてはよくわかりませんが、考えてみると、コンパイラが舞台裏で名前を生成する可能性のある匿名型を使用していますか?コンパイラが実行されるたびに異なる可能性がありますか? ふと思いついた可能性。おそらくジョンスキートのためのものです;-)

更新:おそらく、Reflectorアドインを比較と分解に使用することもできます。

于 2009-09-15T10:41:02.593 に答える
0

あなたは、いくつかのプロジェクトの微調整の後、C++ アプリを同じ SHA1/MD5 値に繰り返しコンパイルできるようになったと言いました。私は、まったく同じ実行可能ファイルを繰り返し再構築する必要があるサードパーティのテスト ラボがある業界にいるという点で、あなたと同じ船に乗っています。

VS2005 でこれを実現する方法を調査しているときに、こちらの投稿に出会いました。C++ アプリを一貫して同じ SHA1/MD5 値にビルドするために行ったプロジェクトの微調整を共有できますか? それは私自身、そしておそらくこの要件を共有する他の人にとって大きな助けになるでしょう.

于 2010-03-17T19:35:39.130 に答える
0

ildasm.exe を使用して両方のプログラムを完全に逆アセンブルし、IL を比較します。次に、テキストベースのメソッドを使用してコードを「クリーン」にし、(予想どおり) コードを再コンパイルします。

于 2013-11-19T06:46:48.573 に答える
0

この質問の答えを見てください。特に 3 番目の外部リンクで提供されています。

編集:

私は実際にこの記事にリンクしたいと思っていました。

于 2009-09-15T10:45:02.773 に答える