如何测试Windows DLL文件以确定它是32位还是64位? [英] How can I test a Windows DLL file to determine if it is 32 bit or 64 bit?

查看:456
本文介绍了如何测试Windows DLL文件以确定它是32位还是64位?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我将使用作为SDK上构建过程结束时的健全检查,以确保64位版本不具有某些32位DLL文件,反之亦然。



有没有简单的方法来查看一个DLL文件并确定它的类型?



解决方案应该在xp32和xp64上工作。

解决方案

Gory细节



一个DLL使用PE可执行格式,它不是很难从文件中读取这些信息。



看到这个。您需要阅读MS-DOS标题,然后阅读 IMAGE_NT_HEADERS 结构。其中包含 IMAGE_FILE_HEADER 结构,其中包含您的信息在包含以下值之一的机器成员中需要




  • IMAGE_FILE_MACHINE_I386(0x014c)

  • IMAGE_FILE_MACHINE_IA64 (0x0200)

  • IMAGE_FILE_MACHINE_AMD64(0x8664)



此信息应为固定偏移量该文件,但我仍然建议遍历文件,并检查MS-DOS标题和IMAGE_NT_HEADERS的签名,以确保您应对任何将来的更改。



使用ImageHelp读取标题...



您还可以使用 ImageHelp API 执行此操作 - 使用 LoadImage ,你会得到一个 LOADED_IMAGE 结构。使用ImageUnload取消分配LOADED_IMAGE。



...或修改这个粗糙的Perl脚本



这里是粗糙的Perl脚本,完成工作。它检查文件有一个DOS头,然后读取从IMAGE_DOS_HEADER 60个字节的PE偏移到文件中。



然后它寻求PE部分的开始,读取签名并进行检查,然后提取我们感兴趣的价值。

 #!/ usr / bin / perl 

#usage:petype< exefile>

$ exe = $ ARGV [0];

打开(EXE,$ exe)或死不能打开$ exe:$!;
binmode(EXE);
if(read(EXE,$ doshdr,64)){

($ magic,$ skip,$ offset)= unpack('a2a58l',$ doshdr);
死(不可执行)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){
printi386\\\
;
}
elsif($ machine == 0x0200){
printIA64 \\\
;
}
elsif($ machine == 0x8664){
printAMD64\\\
;
}
else {
printf(未知机器类型0x%lx\\\
,$ machine);
}
}
}

关闭(EXE);


I'd like to write a test script or program that asserts that all DLL files in a given directory are of a particular build type.

I would use this as a sanity check at the end of a build process on an SDK to make sure that the 64-bit version hasn't somehow got some 32-bit DLL files in it and vice versa.

Is there an easy way to look at a DLL file and determine its type?

The solution should work on both xp32 and xp64.

解决方案

Gory details

A DLL uses the PE executable format, and it's not too tricky to read that information out of the file.

See this MSDN article on the PE File Format for an overview. You need to read the MS-DOS header, then read the IMAGE_NT_HEADERS structure. This contains the IMAGE_FILE_HEADER structure which contains the info you need in the Machine member which contains one of the following values

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

This information should be at a fixed offset in the file, but I'd still recommend traversing the file and checking the signature of the MS-DOS header and the IMAGE_NT_HEADERS to be sure you cope with any future changes.

Use ImageHelp to read the headers...

You can also use the ImageHelp API to do this - load the DLL with LoadImage and you'll get a LOADED_IMAGE structure which will contain a pointer to an IMAGE_NT_HEADERS structure. Deallocate the LOADED_IMAGE with ImageUnload.

...or adapt this rough Perl script

Here's rough Perl script which gets the job done. It checks the file has a DOS header, then reads the PE offset from the IMAGE_DOS_HEADER 60 bytes into the file.

It then seeks to the start of the PE part, reads the signature and checks it, and then extracts the value we're interested in.

#!/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);

这篇关于如何测试Windows DLL文件以确定它是32位还是64位?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆