如何测试 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 的str
是unicode
)。
好吧,那里的示例将其解压缩为有符号值 - 您可能会将其解释为无符号值,但这意味着您有一个 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 <filename>
。我不确定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 Windows,Git 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 加载失败。请确保该二进制储存在路径中,或者调试它以检查该二进制或相关的.DLL文件是不是有问题
无法注册模块C:\windows\system32\aetcngss.dll.HRESULT-2147220473.请与您的技术支持人员联系.