到目前为止,我看了两种方法。两者都没有说服我关于误报或漏报:
使用 PE 标头中的链接器版本字段:我能否通过检查 DLL 本身来判断使用哪个版本的 Visual Studio 来构建 DLL?
判断 PE 可执行文件是否是使用 VisualStudio/gcc 编译的一个很好的启发式方法是什么?
例如,是否有某些字符串、标头值、部分、导入等可以区分它们?确切的编译器版本和使用的编译器标志无关紧要...
我也不期待恶意的可执行文件。
到目前为止,我看了两种方法。两者都没有说服我关于误报或漏报:
使用 PE 标头中的链接器版本字段:我能否通过检查 DLL 本身来判断使用哪个版本的 Visual Studio 来构建 DLL?
判断 PE 可执行文件是否是使用 VisualStudio/gcc 编译的一个很好的启发式方法是什么?
例如,是否有某些字符串、标头值、部分、导入等可以区分它们?确切的编译器版本和使用的编译器标志无关紧要...
我也不期待恶意的可执行文件。
虽然不是确定是否使用 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 使用MOV
inst 而不是PUSH
inst 将值推送到堆栈上。
最好的启发式方法是代码。我会创建一个 hello world 测试文件,并用我感兴趣的编译器编译它。
将它们加载到 IDA 的免费版本(或 Pro,如果你有的话),然后检查入口点的说明。在入口点匹配编译器代码肯定是正确的。您可能必须尝试相同编译器的几个版本,以确保您选择匹配的代码是一致的。
有一个工具堡垒:peid。peid 使用的格式也是用于检测编译器和运行时打包程序(=修改编译程序的程序)的事实上的标准格式。虽然 peid 似乎不再被积极开发,但您可以在网上找到 peid 的最新第三方签名文件。
当然,通过查看 peid 签名,您可以看到它们用于识别编译器的内容。它主要是入口点的代码,即在调用 main() 或 WinMain() 之前运行的指令。