如何确定 PE 可执行文件是用 gcc 还是 VisualStudio 编译的?

逆向工程 聚乙烯 可执行 编译器 二进制格式 海湾合作委员会
2021-06-18 08:06:03

到目前为止,我看了两种方法。两者都没有说服我关于误报或漏报:

  1. 使用字符串:如何检索用于编译给定 ELF 可执行文件的 GCC 版本?

  2. 使用 PE 标头中的链接器版本字段:我能否通过检查 DLL 本身来判断使用哪个版本的 Visual Studio 来构建 DLL?

判断 PE 可执行文件是否是使用 VisualStudio/gcc 编译的一个很好的启发式方法是什么?

例如,是否有某些字符串、标头值、部分、导入等可以区分它们?确切的编译器版本和使用的编译器标志无关紧要...

我也不期待恶意的可执行文件。

4个回答

虽然不是确定是否使用 GCC 或 MSVC (Visual Studio) 的明确方法,但 Rich 标头的存在确实确定是否使用了 Microsoft 的 link.exe(MS VC 工具集的链接器)。(注意:较新的 Visual Studio 也支持使用 clang 构建)

我知道它是官方未公开的,但可以说它是最广为人知和记录在案的公开PE 结构。

Link.exe 总是插入 Rich 标头,没有办法告诉它不这样做。在visualstudio.com 上甚至有人要求添加一个开关来删除它,但官方回应是目前没有办法:https : //developercommunity.visualstudio.com/idea/740443/add-linker-option-to-strip -rich-stamp-from-exe-hea.html即使将“开发人员隐私”作为声明的问题,他们也可能永远不会删除此标头,因为包含的信息与构建环境相关(通常无法识别个人身份),并且目前是一种非常流行的松散链接恶意软件归因的方式。

相反,MinGW、GCC 和其他人不插入此标头。

如果你想要一些 python 代码来检测 Rich 头文件的存在(pefile 模块包含了很多功能来解析和操作头文件):

from pefile import PE

pe = PE('/path/to/file.exe')

rich_header = pe.RICH_HEADER

return rich_header is not None

如果rich_header is None没有标头,否则,它包含标头及其值。

除了 PE 检测工具(如 PEiD、Detect it easy 等)之外,还有一些 GCC 和 MSVC 的特殊代码模式,例如 GCC 使用MOVinst 而不是PUSHinst 将值推送到堆栈上。

最好的启发式方法是代码。我会创建一个 hello world 测试文件,并用我感兴趣的编译器编译它。

将它们加载到 IDA 的免费版本(或 Pro,如果你有的话),然后检查入口点的说明。在入口点匹配编译器代码肯定是正确的。您可能必须尝试相同编译器的几个版本,以确保您选择匹配的代码是一致的。

有一个工具堡垒:peidpeid 使用的格式也是用于检测编译器和运行时打包程序(=修改编译程序的程序)的事实上的标准格式。虽然 peid 似乎不再被积极开发,但您可以在网上找到 peid 的最新第三方签名文件。

当然,通过查看 peid 签名,您可以看到它们用于识别编译器的内容。它主要是入口点的代码,即在调用 main() 或 WinMain() 之前运行的指令。