3

几天前,我不小心在 Notepad++ 中打开了一个商业应用程序的 C++ 可执行文件,发现可执行文件中存储了很多关于原始源代码的信息。

在可执行文件中,我可以找到文件名(app.c、dlgstat.c、...)、函数名(GetTickCount、、DispatchMessageA...)和一小段源代码,主要是条件(szChar != TEXT('\0')iRow < XTGetRows( hwndList ))。之后,我检查了另一个 QT 可执行文件,并且:再次是源文件名和方法签名。

因此,我想知道有多少源代码信息真正存储在 C/C++ 可执行文件中(例如,使用 QT 或 MinGW 编译)。这可能是某种仍然包含原始源的调试版本吗?这些信息是否用于一些反射的东西?出版商有什么理由不删除这些东西吗?

4

3 回答 3

11

有多少源代码信息真正存储在 C/C++ 可执行文件中?

在实践中,并不多。运行时不需要源代码。您命名的字符串来自两件事:

  • 函数名(例如GetTickCount)是从其他模块导入的函数名。这些名称在运行时是必需的,因为函数是动态解析的(通过GetProcAddress使用函数名称调用)。

  • 条件很可能是断言:assert宏将其参数字符串化,以便在触发时您知道未满足什么条件。

如果您构建一个 DLL,它还将包含它导出的所有函数的名称,因此可以在运行时解析它们(对于其他共享对象格式可能也是如此)。

调试符号也可能包含一些原始源代码,尽管它取决于调试符号使用的格式。这些符号可能包含在二进制文件本身或辅助文件中(例如,Windows 上使用的 .pdb 文件)。

于 2012-09-26T22:10:27.167 回答
2

Windows 函数名称:它们可能只是因为它们被动态访问而存在 - 在您的程序中的某个地方有一个GetProcAddress可以获取它们的地址。尽管如此,没有理由担心,每个应用程序都使用 WinAPI,因此从这些信息中没有太多关于您的可执行文件的信息。

条件:可能来自一些assert类似的宏;包含它们以允许assert打印触发失败断言的失败条件。无论如何,在发布模式下,断言应该被自动删除。

源文件名和方法签名:可能来自__FILE____func__宏的一些用法;可能,再次,从assert

有关程序内部结构的其他信息来源是 RTTI,它必须为typeid可能正在处理的每种类型提供一些表示。如果您不需要它的功能,您可以禁用它(但我不知道这在 Qt 项目中是否可行)。

于 2012-09-26T22:12:39.263 回答
0

混合到 C++ 应用程序的二进制文件中,您会发现大多数全局符号的名称(以及调试符号,如果在编译器中启用),但如果它是函数或方法,则带有额外的“装饰文本”,用于编码符号的调用签名. 同样,字符串的文字嵌入在明文中。但是,您在哪里找不到类似编译器用来创建二进制可执行文件的实际源代码的东西。该信息在编译过程中会丢失,如果在构建中使用 C++ 模板,则特别难以进行逆向工程。

于 2012-09-26T22:13:55.507 回答