如何测试 Windows DLL 文件以确定它是 32 位还是 64 位? [复制]

Posted

技术标签:

【中文标题】如何测试 Windows DLL 文件以确定它是 32 位还是 64 位? [复制]【英文标题】:How can I test a Windows DLL file to determine if it is 32 bit or 64 bit? [duplicate] 【发布时间】:2010-10-04 11:02:32 【问题描述】:

我想编写一个测试脚本或程序,断言给定目录中的所有 DLL 文件都属于特定的构建类型。

我会在 SDK 的构建过程结束时使用它作为健全性检查,以确保 64 位版本没有以某种方式在其中包含一些 32 位 DLL 文件,反之亦然。

是否有一种简单的方法可以查看 DLL 文件并确定其类型?

该解决方案应该适用于 xp32 和 xp64。

【问题讨论】:

我很感激,一旦你知道这个问题的答案,***.com/q/197951/5427 分享一个解决方案。然而,提出的问题是不同的。一个明确询问 dll,一个明确询问 exe。这个问题得到了相当多的支持,所以我认为它很好地映射了人们试图找到答案的问题。这里讨论了关于重复的类似想法meta.***.com/q/266244/5427 【参考方案1】:

血腥细节

DLL 使用 PE 可执行格式,从文件中读取该信息并不难。

请参阅此MSDN article on the PE File Format 了解概览。您需要阅读 MS-DOS 标头,然后阅读 IMAGE_NT_HEADERS 结构。这包含 IMAGE_FILE_HEADER 结构,其中包含您在 Machine 成员中需要的信息,其中包含以下值之一

IMAGE_FILE_MACHINE_I386 (0x014c) IMAGE_FILE_MACHINE_IA64 (0x0200) IMAGE_FILE_MACHINE_AMD64 (0x8664)

这些信息应该在文件中的一个固定偏移处,但我仍然建议遍历文件并检查 MS-DOS 标头和 IMAGE_NT_HEADERS 的签名,以确保您应对任何未来的变化。

使用 ImageHelp 读取标题...

您也可以使用ImageHelp API 来执行此操作- 使用LoadImage 加载DLL,您将获得一个LOADED_IMAGE 结构,其中包含指向IMAGE_NT_HEADERS 结构的指针。使用 ImageUnload 释放 LOADED_IMAGE。

...或者改编这个粗略的 Perl 脚本

这是完成工作的粗略 Perl 脚本。它检查文件是否有 DOS 头,然后将 IMAGE_DOS_HEADER 60 字节的 PE 偏移量读取到文件中。

然后它寻找 PE 部分的开头,读取签名并检查它,然后提取我们感兴趣的值。

#!/usr/bin/perl
#
# usage: petype <exefile>
#
$exe = $ARGV[0];

open(EXE, $exe) or die "can't open $exe: $!";
binmode(EXE);
if (read(EXE, $doshdr, 64)) 

   ($magic,$skip,$offset)=unpack('a2a58l', $doshdr);
   die("Not an executable") if ($magic ne 'MZ');

   seek(EXE,$offset,SEEK_SET);
   if (read(EXE, $pehdr, 6))
       ($sig,$skip,$machine)=unpack('a2a2v', $pehdr);
       die("No a PE Executable") if ($sig ne 'PE');

       if ($machine == 0x014c)
            print "i386\n";
       
       elsif ($machine == 0x0200)
            print "IA64\n";
       
       elsif ($machine == 0x8664)
            print "AMD64\n";
       
       else
            printf("Unknown machine type 0x%lx\n", $machine);
       
   


close(EXE);

【讨论】:

非常方便。我为您的代码创建了 Python 翻译:github.com/tgandor/meats/blob/master/missing/arch_of.py @TomaszGandor 很棒的东西。仅供参考,我必须将 'MZ''PE' 更改为 b'MZ'b'PE' 才能正确评估这些 if。不确定这是特定于平台的问题还是什么。 不,这只是意味着你有 Python 3.x ;) 谢谢,已在 GitHub 上修复。我不情愿地迁移到 3.x(写在 2.7 上,试图向前兼容)。所以我有时会忘记,以'rb' 模式打开的文件会返回像b'MZ' 这样的二进制字符串(在Py2 上bytes 只是默认的str,而Py3 的strunicode)。 好吧,那里的示例将其解压缩为有符号值 - 您可能会将其解释为无符号值,但这意味着您有一个 very 大的偏移量。我认为这很不寻常,但您应该能够通过在偏移处找到“PE”来验证无符号偏移是否正确 它以 MZ 开头,但除此之外它看起来像垃圾。这是您期望它的外观en.wikibooks.org/wiki/X86_Disassembly/…【参考方案2】:

如果您安装了 Cygwin(或 MobaXTerm,或适用于 Windows 的 Git Bash,或 WSL,或...)(出于各种原因,我强烈建议您这样做),您可以使用动态链接库

file <filename>

它会给出这样的输出:

icuuc36.dll: MS-DOS executable PE  for MS Windows (DLL) (GUI) Intel 80386 32-bit

【讨论】:

呃...问题出在哪里? file &lt;filename&gt;。我不确定file 是否是核心设置的一部分,或者您是否必须选择它进行安装,但它肯定在 Cygwin 中可用,因为我过去使用过它。 任何使用MingW但没有意识到的人,这也是一个基于Cygwin的东西,它也有这个。 @BradLaney:这很有趣,因为上面的输出是从我的盒子(WinXP / Cygwin)复制和粘贴的。在另一个盒子(Win7)上测试给了我:MS-DOS executable, NE for MS Windows 3.x (driver) 用于“Windows\system\COMMDLG.DLL”,PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit 用于“Program Files\Internet Explorer\iecompat.dll”......此时我停止了测试并且仍然声称,如果你得到的只是“单声道”,要么你只测试了 Mono 程序集,要么你的 Cygwin 安装很糟糕。 64 位 DLL 的示例输出:boost_math_c99f-vc140-mt-1_58.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows 如果您安装了 Git for WindowsGit Bash 控制台中可用的file 命令将代替 Cygwin 工作。 【参考方案3】:

一种粗略的方法是使用每个 DLL 上的 Visual Studio 工具中的 headers 选项调用 dumpbin 并查找适当的输出:

dumpbin /headers my32bit.dll 找到 PE 签名 文件类型:DLL 文件头值 14C机(x86) 1 节数 45499E0A 时间日期戳 Thu Nov 02 03:28:10 2006 0 指向符号表的文件指针 0 符号数 E0 可选标头大小 2102特点 可执行文件 32位字机 动态链接库 可选标题值 10B魔术#(PE32)

您可以在该输出中看到一些线索,表明它是一个 32 位 DLL,包括 Paul 提到的 14C 值。应该很容易在脚本中查找。

【讨论】:

警告:此方法似乎不适用于任何 .NET?为所有 .NET .dll 或 .exe 程序返回 32 位,无论它们是针对 x32 还是 x32/x64(“所有 CPU”)编译的。看起来好像每个 .NET 可执行文件都有一个 32 位本机标头,并且在调用时会调用相应的 32 位或 64 位 .NET 运行时。 有趣。这对我来说似乎没问题,因为 AnyCPU DLL“可以”在 32 位机器上运行。仅 64 位的 .NET DLL 怎么样? @Contango:这并不完全正确(x64 仅 DLL 显示正确的标头,即使 .NET 可执行文件也是如此)。 “任何 CPU”部分是正确的,因为“实际位数”将取决于程序集负载,因此不能在程序集本身中硬编码。您可以使用dumpbin 附带的corflags 实用程序来查看有关.NET 可执行文件的信息。 此处使用corflags的示例***.com/a/2418287/74585 7-zip 归档程序命令行可以做类似的事情。因此,您可以在没有 DumpBin 的 PC 上进行检查。 (参数为l,m前面的字母) "C:\Program Files\7-Zip\"7z l MyFile.dll【参考方案4】:

Dependency Walker 告诉所有(几乎)。 http://www.dependencywalker.com/

它不会“安装”——只需获取它、提取它并运行 exec。 它适用于任何 x32 或 x64 windows 模块|应用程序。

我记得很容易看到所有依赖项,即 dll 模块,并且因为 appl.是一个可以确定它是完整的 x64、x32(x86) 还是每个的位的依赖项的总和。

构建模块的 CPU 类型在“CPU”列中。大多数 64 位应用程序仍然是每个应用程序的一部分,但 32 位应用程序 w/b all x86。

极客/程序员的美丽程序,它是免费的......

【讨论】:

Dependency Walker 似乎不适用于 .NET .dll 或 .exe 文件。使用 32 位和 64 位 .NET 控制台应用程序进行了快速测试,但无法区分。 @Gravitas 对于 .Net 文件,您需要使用 CorFlags.exe 网站下载链接失效。 如果我做这个工作,我只会让用户上传他/她的dll文件并显示信息,而不需要下载任何可执行文件并安装并运行它。 如果文件是64位的,右边会有一个小64的图标。请注意查看感兴趣的文件,而不是其依赖项,因为如果您使用的是 x64 版本的 Depends,它将显示 32 位模块的 64 位依赖项(带有红色图标和错误:Modules with different CPU类型已找到)。【参考方案5】:

我已经写了一个非常简单的工具来做这件事 - 它叫做 PE Deconstructor。

只需启动它并加载您的 DLL 文件:

在上面的例子中,加载的 DLL 是 32 位的。

你可以在这里下载(我只有64位编译的ATM):https://files.quickmediasolutions.com/exe/pedeconstructor_0.1_amd64.exe

此处提供较旧的 32 位版本:https://dl.dropbox.com/u/31080052/pedeconstructor.zip

【讨论】:

我在 PE Deconstructor amd64 可执行文件上试过这个,它说它是 32 位的。 @chrysanhy:这很奇怪 - 有没有其他工具报告可执行文件是 32 位的? 9 年过去了。它说 AMD 64 用于我的 PE Deconstructor 可执行文件

以上是关于如何测试 Windows DLL 文件以确定它是 32 位还是 64 位? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何确定 DLL 中可用的函数以在 Python 中使用

winmm.dll的文件信息

如何确定函数调用正在使用哪个 Windows DLL?

默认输入语言切换器在 Windows 中如何工作?

模块*.DLL 加载失败。请确保该二进制储存在路径中,或者调试它以检查该二进制或相关的.DLL文件是不是有问题

无法注册模块C:\windows\system32\aetcngss.dll.HRESULT-2147220473.请与您的技术支持人员联系.