简体   繁体   English

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

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

I need to find the mode EXE/DLL was build looking at its headers.我需要找到模式 EXE/DLL 是在其头文件中构建的。 (Using C++ only without any external tools) (仅使用 C++,无需任何外部工具)

There is an old discussion on how to determine if DLL was built in Release or Debug mode.有一个关于如何确定 DLL 是在发布模式还是调试模式下构建的旧讨论。 http://forums.codeguru.com/archive/index.php/t-485996.html http://forums.codeguru.com/archive/index.php/t-485996.html

But unfortunately, I did not find any clear answer.但不幸的是,我没有找到任何明确的答案。

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 of possible, within limits, and unreliably.如果“头”你的意思是PE部分或资源(头不会告诉你任何东西,程序通常不与他们开发头发货!),这是一种可能的限度内,并且不可靠。 Otherwise, this is an entirely impossible endeavour unless you wrote the program yourself.否则,除非您自己编写程序,否则这是完全不可能的努力。

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.通常,很难以可靠的方式做这样的事情,更何况“调试构建”是 Microsoft Visual Studio 的简化,在大多数编译器下都不存在。 For example, with GCC it is perfectly allowable to have an optimized build that nevertheless contains debug symbols.例如,对于 GCC,完全允许优化构建但包含调试符号。 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.甚至可以使用#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$S and .debug$T contain debug symbols and debug types, respectively. .debug$S.debug$T包含调试符号和调试类型。 There are some other sections starting with .debug as well, but they're deprecated.还有一些其他部分也以.debug开头,但它们已被弃用。 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.在不使用外部工具的情况下使用 C++,您将需要跳过 DOS“MZ”存根和 PE 头文件。 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 .debug will be just as good.最有可能的是,读入文件并对.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.同样,您可以查看 VERSIONINFO 或清单文件(它们还允许指定程序是否为调试版本),但这些不是强制性的。 You can write pretty much anything you want into these.您几乎可以在其中写入任何您想要的内容。 Insofar, they're even less reliable than looking for debug symbols.就目前而言,它们甚至不如查找调试符号可靠。

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 assert function (which you could do with a simple string match), since the assert macro (from which it's normally called) is entirely stripped out in a build with NDEBUG defined.下一个最好的猜测是没有调用 CRT assert函数(您可以使用简单的字符串匹配来实现),因为assert宏(通常从中调用它)在定义了NDEBUG的构建中被完全剥离。 No use of that symbol, no string present in the binary.不使用该符号,二进制中不存在字符串。
Unluckily, a program that doesn't have any asserts would be falsely identified as "release build" regardless of its actual build, and it is entirely possible to redefine the assert macro to do something completely different (such as printf a text and continue).不幸的是,一个没有任何断言的程序会被错误地识别为“发布构建”,而不管它的实际构建如何,并且完全有可能重新定义assert宏来做一些完全不同的事情(例如printf a 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 assert that you don't know about.最后,您不知道您链接的某些静态 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.可能需要 2-3 次尝试才能使其恰到好处,但基本上它应该像定义一个变量(或导出函数,如果您的编译器/链接器不导出未使用的符号)并编写两三个一样简单无法访问的程序位置的魔法值。 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.如果它们不存在,则它是优化的构建。

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 explained here 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 images are 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).事实上,几乎所有 Windows 操作系统映像文件都构建有调试支持(否则,不可能将这些已发布的映像与来自 Microsoft 符号服务器的符号文件链接起来)。 Even though these images are Release images!即使这些图像是发布图像!

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 规范中不起作用,部分的名称可以根据需要更改和设置 - 加载程序不关心它!)不是一个发布与调试图像的指示器。

There is an old reversing tool called LordPE.有一个叫做 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.我在 VS2008 中在 Release 和 Debug 模式下编译了一个“hello world”程序并进行了比较。 As in the other posters, I didn't see anything that would serve as an indicator.和其他海报一样,我没有看到任何可以作为指标的东西。

But what I did find as an indicator was the padding in the .text section of the binary.但是我确实发现作为一个指标的是二进制文件的 .text 部分中的填充。 There is over a hundred bytes with the value 0xCC after the last byte of code in the .text section in the Debug version.在 Debug 版本的 .text 部分的最后一个代码字节之后,有超过一百个字节的值为 0xCC。 In the Release version, there were no 0xCC bytes.在 Release 版本中,没有 0xCC 字节。 0xCC bytes will show up as int3 or breakpoints in a debugger. 0xCC 字节将在调试器中显示为 int3 或断点。

When you create a C++ project in Visual Studio it generates two configurations for you.当您在 Visual Studio 中创建 C++ 项目时,它会为您生成两个配置。 The names of these configurations are Debug and Release .这些配置的名称是DebugRelease The Debug configuration includes generation of debug information, less optimization and support for Edit&Continue. 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 _DEBUG was defined.您可以尝试确定是否定义了预处理器符号_DEBUG 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. FILEFLAGES 字段的位 0 通常表示在编译资源时定义了符号 _DEBUG。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM