簡體   English   中英

如何檢查可執行文件或 DLL 是在發布還是調試模式下構建的 (C++)

[英]How to check if an executable or DLL is build in Release or Debug mode (C++)

我需要找到模式 EXE/DLL 是在其頭文件中構建的。 (僅使用 C++,無需任何外部工具)

有一個關於如何確定 DLL 是在發布模式還是調試模式下構建的舊討論。 http://forums.codeguru.com/archive/index.php/t-485996.html

但不幸的是,我沒有找到任何明確的答案。

我需要找到模式 exe/dll 是在查看其標頭時構建的。

如果“頭”你的意思是PE部分或資源(頭不會告訴你任何東西,程序通常不與他們開發頭發貨!),這是一種可能的限度內,並且不可靠。 否則,除非您自己編寫程序,否則這是完全不可能的努力。

通常,很難以可靠的方式做這樣的事情,更何況“調試構建”是 Microsoft Visual Studio 的簡化,在大多數編譯器下都不存在。 例如,對於 GCC,完全允許優化構建但包含調試符號。 甚至可以使用#pragma打開和關閉優化(並更改優化級別甚至目標機器!),從而在未優化的構建中優化函數(或函數組),反之亦然。

調試符號的存在是您對不是您編寫的程序的最佳猜測。 從生成的二進制文件中判斷它是否已被優化是不可能的(無論如何,這並不現實,以簡單、自動化的方式)。

.debug$S.debug$T包含調試符號和調試類型。 還有一些其他部分也以.debug開頭,但它們已被棄用。 以“調試模式”構建且隨后未被剝離的程序將包含部分或全部這些部分。
在不使用外部工具的情況下使用 C++,您將需要跳過 DOS“MZ”存根和 PE 頭文件。 在此之后是部分標題,您可以對其進行解析。 可以在此處下載文件格式的完整文檔。
最有可能的是,讀入文件並對.debug進行字符串匹配也一樣好。

同樣,您可以查看 VERSIONINFO 或清單文件(它們還允許指定程序是否為調試版本),但這些不是強制性的。 您幾乎可以在其中寫入任何您想要的內容。 就目前而言,它們甚至不如查找調試符號可靠。

另一個不可靠的提示是檢查程序所鏈接的系統庫的版本。 如果是調試版本,則很可能是調試版本。 但是,您可以進行發布構建並仍然與調試庫鏈接,沒有什么可以阻止您這樣做。

下一個最好的猜測是沒有調用 CRT assert函數(您可以使用簡單的字符串匹配來實現),因為assert宏(通常從中調用它)在定義了NDEBUG的構建中被完全剝離。 不使用該符號,二進制中不存在字符串。
不幸的是,一個沒有任何斷言的程序會被錯誤地識別為“發布構建”,而不管它的實際構建如何,並且完全有可能重新定義assert宏來做一些完全不同的事情(例如printf a text and continue) . 最后,您不知道您鏈接的某些靜態 3rd 方庫(顯然已經通過了預處理器)是否包含assert您不知道的調用。

如果您想檢查自己編寫的程序,您可以利用優化器將完全刪除可證明無法訪問或未使用的內容這一事實。 可能需要 2-3 次嘗試才能使其恰到好處,但基本上它應該像定義一個變量(或導出函數,如果您的編譯器/鏈接器不導出未使用的符號)並編寫兩三個一樣簡單無法訪問的程序位置的魔法值。 優化編譯器至少會將這幾個多余的動作合並為一個,或者更有可能將它們全部消除。
然后,您可以對魔術值進行二進制字符串搜索。 如果它們不存在,則它是優化的構建。

這個問題非常好,正如已經說過的,沒有真正明顯(獨特)的指標來標記圖像是調試還是發布。

正如這里和這里解釋的,調試目錄的存在並不是關於圖像是否已在發布模式下構建的指標。 發布的鏡像構建時帶有調試支持是很常見的。 事實上,幾乎所有 Windows 操作系統映像文件都構建有調試支持(否則,不可能將這些已發布的映像與來自 Microsoft 符號服務器的符號文件鏈接起來)。 即使這些圖像是發布圖像!

甚至 .debug 部分的存在(實際上,部分名稱在 PE 規范中不起作用,部分的名稱可以根據需要更改和設置 - 加載程序不關心它!)不是一個發布與調試圖像的指示器。

有一個叫做 LordPE 的舊逆向工具。 它將允許您打開兩個文件並區分標題。 我在 VS2008 中在 Release 和 Debug 模式下編譯了一個“hello world”程序並進行了比較。 和其他海報一樣,我沒有看到任何可以作為指標的東西。

但是我確實發現作為一個指標的是二進制文件的 .text 部分中的填充。 在 Debug 版本的 .text 部分的最后一個代碼字節之后,有超過一百個字節的值為 0xCC。 在 Release 版本中,沒有 0xCC 字節。 0xCC 字節將在調試器中顯示為 int3 或斷點。

當您在 Visual Studio 中創建 C++ 項目時,它會為您生成兩個配置。 這些配置的名稱是DebugRelease Debug 配置包括調試信息的生成、較少的優化和對 Edit&Continue 的支持。

但這只是一個起點。 您可以創建任意配置,甚至可以將所有調試信息添加到發布配置中。 所以沒有明確的 Debug 或 Release 構建。

您可以嘗試確定是否定義了預處理器符號_DEBUG 這很少改變,它在版本資源中使用。 FILEFLAGES 字段的位 0 通常表示在編譯資源時定義了符號 _DEBUG。

由於我必須檢查數百個 dll 和 exe,因此我嘗試了 Smerlin 的建議,方法是在控制台模式下運行depends.exe(2.2 版)並在depends 生成的輸出文件中搜索“MSVCRTD”。

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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM