19

EXE/DLLがビルドされたモードをヘッダーで確認する必要があります。(外部ツールなしでのみC ++を使用)

DLLがリリースモードとデバッグモードのどちらでビルドされたかを判断する方法については、古い議論があります。 http://forums.codeguru.com/archive/index.php/t-485996.html

しかし、残念ながら、明確な答えは見つかりませんでした。

4

5 に答える 5

9

exe/dllがビルドされたモードをヘッダーで確認する必要があります。

「ヘッダー」とは、PEセクションまたはリソースを意味する場合(ヘッダーは何も通知せず、プログラムは通常、開発ヘッダーとともに出荷されません!)、これは、制限内で、信頼性の低い方法で可能です。そうでなければ、あなたが自分でプログラムを書かない限り、これは完全に不可能な試みです。

一般に、このようなことを信頼できる方法で行うことは困難です。「デバッグビルド」は、ほとんどのコンパイラではそのように存在しないMicrosoftVisualStudioの簡略化であるためです。たとえば、GCCでは、デバッグシンボルを含む最適化されたビルドを使用することは完全に許容されます。最適化のオンとオフを#pragma切り替えたり(最適化レベルやターゲットマシンを変更したりすることもできます)、最適化されていないビルドで最適化された関数(または関数のグループ)を使用することもできます。その逆も可能です。

デバッグシンボルの存在は、作成しなかったプログラムの最良の推測です。生成されたバイナリから、最適化されているかどうかを判断することはできません(現実的には、単純で自動化された方法ではありません)。

セクション.debug$S.debug$Tには、それぞれデバッグシンボルとデバッグタイプが含まれています。で始まる他のセクションもいくつかあります.debugが、それらは非推奨です。「デバッグモード」でビルドされ、その後削除されていないプログラムには、これらのセクションの一部またはすべてが含まれます。
外部ツールなしでC++を使用する場合は、DOSの「MZ」スタブとPEヘッダーをスキップする必要があります。この後、解析できるセクションヘッダーが表示されます。ファイル形式の完全なドキュメントは、ここからダウンロードできます。
おそらく、ファイルを読み込んで文字列の一致を実行するの.debugも同じくらい良いでしょう。

同様に、VERSIONINFOまたはマニフェストファイル(プログラムがデバッグビルドであるかどうかを指定することもできます)を確認できますが、これらは必須ではありません。あなたはこれらにあなたが望むほとんど何でも書くことができます。これまでのところ、デバッグシンボルを探すよりも信頼性は低くなります。

もう1つのヒントは、プログラムがリンクされているシステムライブラリのバージョンを確認することです。デバッグバージョンの場合は、デバッグビルドである可能性があります。ただし、リリースビルドを実行しても、デバッグライブラリとリンクすることはできますが、それを妨げるものは何もありません。

次善の推測は、CRTassert関数への呼び出しがないことです(これは単純な文字列の一致で行うことができます)。これは、assertマクロ(通常はそこから呼び出されます)がNDEBUG定義済みのビルドで完全に削除されるためです。その記号は使用せず、バイナリに文字列は存在しません。残念ながら、アサートがない
プログラムは、実際のビルドに関係なく「リリースビルド」として誤って識別され、マクロを再定義してまったく異なること(テキストや続行など)を実行することは完全に可能です。そして最後に、リンク先の静的なサードパーティライブラリ(明らかにプリプロセッサを通過している)に、知らない呼び出しが含まれているかどうかはわかりません。assertprintfassert

自分で作成したプログラムを確認したい場合は、オプティマイザーが到達不能または使用されていないものを完全に削除するという事実を利用できます。正しく取得するには2〜3回の試行が必要になる場合がありますが、基本的には、変数(または、コンパイラ/リンカーが使用されていないシンボルをエクスポートしない場合はエクスポートされた関数)を定義し、2〜3回書き込むだけの簡単なものにする必要があります。到達できないプログラムの場所からそれに魔法の値。最適化コンパイラは、少なくともこれらのいくつかの冗長な動きを1つにまとめるか、おそらくそれらすべてを完全に排除します。
次に、マジック値のバイナリ文字列検索を実行できます。それらが存在しない場合は、最適化されたビルドです。

于 2012-06-20T09:49:23.740 に答える
2

質問は非常に優れており、すでに述べたように、イメージがデバッグされているかリリースされているかを示す実際の明白な(一意の)インジケーターはありません。

こことここで説明されているように、デバッグディレクトリの存在は、イメージがリリースモードでビルドされているかどうかを示すものではありません。リリースされたイメージがデバッグサポートを使用してビルドされることは非常に一般的です。実際のところ、ほとんどすべてのWindows OSイメージファイルはデバッグサポートを使用して構築されています(そうでない場合、これらのリリースされたイメージをMicrosoft Symbols Serverのシンボルファイルにリンクすることはできません)。これらの画像はリリース画像ですが!

.debugセクションの存在でさえ(実際には、セクション名はPE仕様では役割を果たしません。セクションの名前は、必要に応じて変更および設定できます。ローダーはそれを気にしません!)リリース対デバッグイメージのインジケータ。

于 2012-06-20T11:23:53.880 に答える
2

LordPEと呼ばれる古い反転ツールがあります。これにより、2つのファイルを開いて、ヘッダーを比較できます。VS2008のリリースモードとデバッグモードで「helloworld」プログラムをコンパイルし、それらを比較しました。他のポスターと同じように、指標となるものは何も見当たりませんでした。

しかし、インジケーターとして私が見つけたのは、バイナリの.textセクションのパディングでした。デバッグバージョンの.textセクションのコードの最後のバイトの後に値が0xCCの100バイトを超えています。リリースバージョンでは、0xCCバイトはありませんでした。0xCCバイトは、デバッガーでint3またはブレークポイントとして表示されます。

于 2014-07-21T02:32:49.130 に答える
1

VisualStudioでC++プロジェクトを作成すると、2つの構成が生成されます。これらの構成の名前は、DebugおよびReleaseです。デバッグ構成には、デバッグ情報の生成、最適化の削減、およびEdit&Continueのサポートが含まれます。

しかし、これは出発点にすぎません。任意の構成を作成し、すべてのデバッグ情報をリリース構成に追加することもできます。したがって、明確なデバッグまたはリリースビルドはありません。

プリプロセッサシンボル_DEBUGが定義されているかどうかを識別してみることができます。これはめったに変更されず、バージョンリソースで使用されます。FILEFLAGESフィールドのビット0は通常、リソースのコンパイル時にシンボル_DEBUGが定義されたことを示します。

于 2012-06-20T11:08:27.933 に答える
0

何百ものdllとexeをチェックする必要があったので、コンソールモードでdepends.exe(ver 2.2)を実行し、dependsによって生成された出力ファイルで「MSVCRTD」を検索して、Smerlinの提案を試しました。

Process p = new Process();
dllWalkerPath = "\""+ dllWalkerPath + "\"";
binaryFilePath = Path.GetFullPath(binaryFilePath); //path to folder containing the dll's to be verified
string exePath = Assembly.GetEntryAssembly().Location;
string outputFilePath = Path.GetDirectoryName(exePath) + dependsOutputName;
p.StartInfo = new ProcessStartInfo(dllWalkerPath, @"/c /oc:" + outputFilePath + " " + binaryFilePath) //dllWalkerPath contains the path to depends.exe 2.2
{
    UseShellExecute = false
};
p.Start();
p.WaitForExit();
于 2018-12-12T10:37:37.357 に答える