275

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

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

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

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

4

5 回答 5

174

一种粗略的方法是使用每个 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 值。应该很容易在脚本中查找。

于 2009-01-30T12:30:50.097 回答
128

如果您安装了Cygwin(或 MobaXTerm,或适用于 Windows 的 Git Bash,或 WSL,或...)(出于各种原因,我强烈建议您这样做),您可以使用 DLL 上的“文件”实用程序

file <filename>

这将给出这样的输出:

icuuc36.dll: MS-DOS executable PE  for MS Windows (DLL) (GUI) Intel 80386 32-bit
于 2009-01-30T12:30:01.847 回答
113

血腥细节

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

有关概述,请参阅有关 PE 文件格式的 MSDN 文章。您需要读取 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);
于 2009-01-30T12:06:36.607 回答
49

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

它不会“安装” - 只是获取它,提取它并运行 exec。它适用于任何 x32 或 x64 Windows 模块|应用程序。

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

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

极客/程序员的漂亮程序,它是免费的......

于 2011-01-27T03:35:13.147 回答
45

我已经编写了一个非常简单的工具来完成这个任务——它叫做 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

于 2012-03-01T23:21:48.623 回答