如何检查可执行文件或 DLL 是在发布还是调试模式下构建的 (C++)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11115832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:52:13  来源:igfitidea点击:

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

c++dllexedebug-symbolsportable-executable

提问by ChatCloud

I need to find the mode exe/dll was build looking at its headers. [edit] Using c++ only without any external tools.[/edit]

我需要找到模式 exe/dll 是在查看其标头时构建的。[编辑] 在没有任何外部工具的情况下仅使用 C++。[/编辑]

There is an old discussion how to determine dll was built in Release or Debug mode. http://forums.codeguru.com/archive/index.php/t-485996.html

有一个古老的讨论如何确定 dll 是在 Release 还是 Debug 模式下构建的。 http://forums.codeguru.com/archive/index.php/t-485996.html

But unfortunately I did not find any clear answer.

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

采纳答案by Damon

I need to find the mode exe/dll was build looking at its headers.

我需要找到模式 exe/dll 是在查看其标头时构建的。

If by "headers" you mean PE sections or resources (headers won't tell you anything, and programs are not usually shipped with their development headers!), this is kind ofpossible, within limits, and unreliably. Otherwise, this is an entirely impossible endeavour unless you wrote the program yourself.

如果“头”你的意思是PE部分或资源(头不会告诉你任何东西,程序通常不与他们开发头发货!),这是一种可能的限度内,并且不可靠。否则,除非您自己编写程序,否则这是完全不可能的努力。

Generally, it is hard to do such a thing in a reliable way, even more so as "debug build" is a Microsoft Visual Studio simplification that does not exist as such under most compilers. For example, with GCC it is perfectly allowable to have an optimized buildthat nevertheless contains debug symbols. It is even possible to turn optimizations on and off with #pragma(and change the optimization level and even the target machine!) and thus have optimized functions (or groups of functions) in an unoptimized build, and vice versa.

通常,很难以可靠的方式做这样的事情,更何况“调试构建”是 Microsoft Visual Studio 的简化,在大多数编译器下都不存在。例如,对于 GCC,完全允许优化构建但包含调试符号。甚至可以打开和关闭优化#pragma(并更改优化级别甚至目标机器!),从而在未优化的构建中优化功能(或功能组),反之亦然。

The presence of debug symbols is your best guess for a program that you didn't write. It is not possible (not realistically, in a simple, automated way, anyway) to tell from a generated binary whether it has been optimized or not.

调试符号的存在是您对不是您编写的程序的最佳猜测。从生成的二进制文件中判断它是否已被优化是不可能的(无论如何,这并不现实,以简单、自动化的方式)。

The sections .debug$Sand .debug$Tcontain debug symbols and debug types, respectively. There are some other sections starting with .debugas well, but they're deprecated. A program that has been built in "debug mode" and that has not afterwards been stripped will contain some or all of these sections.
Using C++ with no external tools, you will want to skip over the DOS "MZ" stub and the PE header. After this come the section headers, which you can parse. Complete documenation of the file format can be downloaded here.
Most probably, reading the file in and doing a string match for .debugwill be just as good.

部分.debug$S和分别.debug$T包含调试符号和调试类型。还有一些其他部分也以 开头.debug,但它们已被弃用。以“调试模式”构建且随后未被剥离的程序将包含部分或全部这些部分。
在不使用外部工具的情况下使用 C++,您将需要跳过 DOS“MZ”存根和 PE 头文件。在此之后是部分标题,您可以对其进行解析。可以在此处下载文件格式的完整文档。
最有可能的是,读入文件并进行字符串匹配.debug也一样好。

Similarly, you can look at VERSIONINFO or the manifest file (they also allow to specify whether a program is a debug build), but these are not mandatory. You can write pretty much anything you want into these. Insofar, they're even less reliable than looking for debug symbols.

同样,您可以查看 VERSIONINFO 或清单文件(它们还允许指定程序是否为调试版本),但这些不是强制性的。您几乎可以在其中写入任何您想要的内容。就目前而言,它们甚至不如查找调试符号可靠。

Another hint, unreliable again, would be to check what versions of system libraries a program was linked with. If it's the debug version, chances are it was a debug build. However, one could do a release build and still link with debug libraries, nothing can prevent you from doing that.

另一个不可靠的提示是检查程序所链接的系统库的版本。如果是调试版本,则很可能是调试版本。但是,您可以进行发布构建并仍然与调试库链接,没有什么可以阻止您这样做。

The next best guess would be the absence of calls to the CRT assertfunction (which you could do with a simple string match), since the assertmacro (from which it's normally called) is entirely stripped out in a build with NDEBUGdefined. No use of that symbol, no string present in the binary.
Unluckily, a program that doesn't haveany asserts would be falsely identified as "release build" regardless of its actual build, and it is entirely possible to redefine the assertmacro to do something completely different (such as printfa text and continue). And lastly, you don't know wheter some static 3rd party library that you link with (which obviously has already passed the preprocessor) contains calls to assertthat you don't know about.

下一个最好的猜测是没有调用 CRTassert函数(您可以使用简单的字符串匹配来完成),因为assert宏(通常从中调用它)在具有NDEBUG定义的构建中完全剥离。不使用该符号,二进制中不存在字符串。
不幸的是,一个没有任何断言的程序会被错误地识别为“发布构建”,而不管它的实际构建如何,并且完全有可能重新定义assert宏来做一些完全不同的事情(例如printf文本和继续)。最后,您不知道您链接的某些静态 3rd 方库(显然已经通过了预处理器)是否包含assert您不知道的调用。

If you want to check a program that you wrote yourself, you can exploit the fact that the optimizer will completely remove things that are provably unreachable or not used. It may take 2-3 attempts to get it just right, but basically it should be as simple as defining a variable (or an exported function if your compiler/linker doesn't export symbols that aren't used) and writing two or three magic values to it from a program location that is not reachable. An optimizing compiler will at least collapse those several redundant moves into one, or more likely entirely eleminate them all.
You can then just do a binary string search for the magic values. If they're not present, it's an optimized build.

如果您想检查自己编写的程序,您可以利用优化器将完全删除可证明无法访问或未使用的内容这一事实。可能需要 2-3 次尝试才能使其恰到好处,但基本上它应该像定义一个变量(或导出函数,如果您的编译器/链接器不导出未使用的符号)并编写两三个一样简单无法访问的程序位置的魔法值。优化编译器至少会将这几个多余的动作合并为一个,或者更有可能将它们全部消除。
然后,您可以对魔术值进行二进制字符串搜索。如果它们不存在,则它是优化的构建。

回答by mox

The question is very good, and as already stated, there are no real obvious (unique) indicators that flag of whether or not an image is debug or released.

这个问题非常好,正如已经说过的,没有真正明显(独特)的指标来标记图像是调试还是发布。

As explainedhere and here, the presence of a Debug Directory is NOT an indicator about whether or not an image has been built in Release Mode. It is very common that released imagesare built with debug support . As a matter of fact, almost ALL Windows OS image files are built with debug support (otherwise, there would be NO possibility to link these Released images with the symbols files from the Microsoft Symbols Server). Even though these images are Release images!

正如这里和这里解释的,调试目录的存在并不是关于图像是否已在发布模式下构建的指标。发布的镜像构建时带有调试支持是很常见的。事实上,几乎所有 Windows 操作系统映像文件都构建有调试支持(否则,不可能将这些已发布的映像与来自 Microsoft 符号服务器的符号文件链接起来)。即使这些图像是发布图像!

Even the presence of the .debug section (actually, Sections names do NOT plays a role in the PE specification, the name of a section can be changed and set as you wish - the Loader don't care about it!) is NOT an indicator of Release vs. Debug image.

甚至 .debug 部分的存在(实际上,部分名称在 PE 规范中不起作用,部分的名称可以根据需要更改和设置 - 加载程序不关心它!)不是一个发布与调试图像的指示器。

回答by lynxjerm

There is an old reversing tool called LordPE. It will allow you to open two files and diff the headers. I compiled a "hello world" program in VS2008 in Release and Debug mode and compared them. As in the other posters, I didn't see anything that would serve as an indicator.

有一个叫做 LordPE 的旧逆向工具。它将允许您打开两个文件并区分标题。我在 VS2008 中在 Release 和 Debug 模式下编译了一个“hello world”程序并进行了比较。和其他海报一样,我没有看到任何可以作为指标的东西。

But what I did find as an indicator was the padding in the .text section of the binary. There is over a hundred bytes with the value 0xCC after the last byte of code in the .text section in the Debug version. In the Release version, there were no 0xCC bytes. 0xCC bytes will show up as int3 or breakpoints in a debugger.

但是我确实发现作为一个指标的是二进制文件的 .text 部分中的填充。在 Debug 版本的 .text 部分的最后一个代码字节之后,有超过一百个字节的值为 0xCC。在 Release 版本中,没有 0xCC 字节。0xCC 字节将在调试器中显示为 int3 或断点。

回答by Martin

As i had to check hundreds of dll's and exe, i tried Smerlin's suggestion by running depends.exe (ver 2.2) in console mode and searching for "MSVCRTD" in the output file generated by depends.

由于我必须检查数百个 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();

回答by harper

When you create a C++ project in Visual Studio it generates two configurations for you. The names of these configurations are Debugand Release. The Debug configuration includes generation of debug information, less optimization and support for Edit&Continue.

当您在 Visual Studio 中创建 C++ 项目时,它会为您生成两个配置。这些配置的名称是DebugRelease。Debug 配置包括调试信息的生成、较少的优化和对 Edit&Continue 的支持。

But this is only a starting point. You can create arbitrary configurations and even add all debug information to the Release configuration. So there is no clear Debug or Release build.

但这只是一个起点。您可以创建任意配置,甚至可以将所有调试信息添加到发布配置中。所以没有明确的 Debug 或 Release 构建。

You can try to identify if the preprocessor symbol _DEBUGwas defined. This is seldom changed and it is used in the version resource. The bit 0 of the FILEFLAGES field usually indicates that the symbols _DEBUG was defined when compiling the resource.

您可以尝试确定是否_DEBUG定义了预处理器符号。这很少改变,它在版本资源中使用。FILEFLAGES 字段的位 0 通常表示在编译资源时定义了符号 _DEBUG。