如何确定可执行文件是针对哪个平台编译的?
我需要使用为 x86、x64 和 IA64 制作的 Windows 可执行文件。 我想通过检查文件本身以编程方式找出平台。
我的目标语言是 PowerShell,但 C# 示例就可以了。 如果您知道其中的任何一个失败,那就太好了。
I have a need to work with Windows executables which are made for x86, x64, and IA64. I'd like to programmatically figure out the platform by examining the files themselves.
My target language is PowerShell but a C# example will do. Failing either of those, if you know the logic required that would be great.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
如果您安装了 Visual Studio,则可以使用
dumpbin.exe
。 PowerShell 社区扩展 中还有可用于测试的Get-PEHeader
cmdlet对于可执行图像。Dumpbin 将把 DLL 报告为
machine (x86)
或machine (x64)
Get-PEHeader 将把 DLL 报告为
PE32
或PE32+< /代码>
If you have Visual Studio installed you can use
dumpbin.exe
. There's also theGet-PEHeader
cmdlet in the PowerShell Community Extensions that can be used to test for executable images.Dumpbin will report DLLs as
machine (x86)
ormachine (x64)
Get-PEHeader will report DLLs as either
PE32
orPE32+
(来自另一个问题,已删除)
机器类型:这是我基于一些获取链接器时间戳的快速代码。 这是在同一个标头中,并且似乎有效 - 当编译任何 cpu- 时它返回 I386,当用它作为目标平台编译时返回 x64。
探索 PE 标头(K. Stanton,MSDN)博客条目向我展示了偏移量,正如另一个回复指出的那样。
(from another Q, since removed)
Machine type: This is a quick little bit of code I based on some that gets the linker timestamp. This is in the same header, and it seems to work - it returns I386 when compiled -any cpu-, and x64 when compiled with that as the target platform.
The Exploring PE Headers (K. Stanton,MSDN) blog entry that showed me the offset, as another response noted.
您需要 GetBinaryType win32 函数。 这将返回 PE 格式可执行文件的相关部分。
通常,您会在 BinaryType 字段中获得 SCS_32BIT_BINARY 或 SCS_64BIT_BINARY,
或者您可以检查 PE 格式本身以查看可执行文件是为哪种体系结构编译的。
IMAGE_FILE_HEADER.Machine 字段将为 IA64 二进制文件设置“IMAGE_FILE_MACHINE_IA64”,为 32 位设置 IMAGE_FILE_MACHINE_I386,为 64 位设置 IMAGE_FILE_MACHINE_AMD64(即 x86_64)。
有一篇 MSDN 杂志文章可以帮助您入门。
附录:这可能会对您有更多帮助。 您将二进制文件作为文件读取:检查前 2 个字节为“MZ”,然后跳过接下来的 58 个字节并将 60 个字节处的神奇 32 位值读取到映像中(对于 PE 可执行文件来说等于 0x00004550)。 以下字节是此标头,前 2 个其中的字节告诉您二进制文件是为哪台机器设计的(0x8664 = x86_64、0x0200 = IA64、0x014c = i386)。
(执行摘要:读取文件的第 65 和 66 字节以获取图像类型)
You need the GetBinaryType win32 function. This will return the relevant parts of the PE-format executable.
Typically, you'll get either SCS_32BIT_BINARY or SCS_64BIT_BINARY in the BinaryType field,
Alternativaly you can check the PE format itself to see what architecture the executable is compiled for.
The IMAGE_FILE_HEADER.Machine field will have "IMAGE_FILE_MACHINE_IA64" set for IA64 binaries, IMAGE_FILE_MACHINE_I386 for 32-bit and IMAGE_FILE_MACHINE_AMD64 for 64-bit (ie x86_64).
There's a MSDN magazine article to help you get going.
Addendum: This may help you a little more. You read the binary as a file: check the first 2 bytes say "MZ", then skip the next 58 bytes and read the magic 32-bit value at 60 bytes into the image (which equals 0x00004550 for PE executables). The following bytes are this header, the first 2 bytes of which tell you which machine the binary is designed for (0x8664 = x86_64, 0x0200 = IA64, 0x014c = i386).
(executive summary: read bytes 65 and 66 of the file to get the image type)
根据“确定应用程序是否为 32 位编译的 10 种方法”位还是 64 位”,您可以通过用记事本打开 DLL 或 EXE 并查找
PE
来检查它是 32 位还是 64 位开头 - 如果后面的第三个字母是:L
,则平台是 32 位:d
平台为64位:我在我的 DLL 上尝试了它,它似乎是准确的。
According to "10 Ways to Determine if Application is Compiled for 32-bit or 64-bit", you can check if a DLL or EXE is 32-bit or 64-bit by opening it with Notepad and looking for
PE
at the beginning - if the 3rd letter after that is:L
the platform is 32-bit:d
the platform is 64-bit:I tried it on my DLLs and it seems to be accurate.
目标机器应该在机器中。
不过,这只适用于 .NET 程序集。
The target machine should then be in machine.
That'll only work with .NET assemblies though.
Visual Studio 的
bin
目录下提供的dumpbin.exe
适用于.lib
和.dll
dumpbin.exe
available underbin
directory of Visual Studio works for both.lib
and.dll
Unix 操作系统有一个名为“file”的实用程序,用于识别文件。 识别规则保存在一个名为“magic”的描述文件中。 您可以尝试 file 看看它是否能够正确识别您的文件并从魔术文件中获取适当的规则。
Unix OS have a utility called "file" which identifies files. The rules for identifying are kept in a description file called "magic". You could try file to see if it is able to identify your files correctly and grab the appropriate rules out of the magic file.
我可以提供一些 C# 代码的链接访问 IMAGE_FILE_HEADER,我认为它可以(轻松)编译到 PowerShell cmdlet 中。 我相当确定您不能直接在 PowerShell 脚本中使用该方法,因为它缺少指针和 PInvoke 功能。
然而,您应该能够利用您现在对 PE 标头格式的广泛了解;-)“直接”找到正确的字节并找出它。 这将在PowerShell脚本中工作,并且您应该能够仅转换此 C# 代码来自 Tasos 博客 到脚本。 我不会在这里重复代码,因为它不是我的。
I can offer a link to some C# code for accessing the IMAGE_FILE_HEADER, which I think could be (easily) compiled into a PowerShell cmdlet. I'm reasonably sure you can't use that method in PowerShell script directly, since it lacks pointers and PInvoke capability.
However, you should be able to use your by now extensive knowledge of the PE header format ;-) to just go "straight" to the right bytes and figure it out. This will work in PowerShell script, and you should be able to just convert this C# code from Tasos' blog to script. I won't bother repeating the code here since it's not mine.
这是 C 中的实现。
Here is an implementation in C.
下面是一个 C++ MFC 控制台应用程序,用于写出文件头信息。 您可以检查特征中的机器类型(IMAGE_FILE_HEADER Machine 成员)或 IMAGE_FILE_32BIT_MACHINE 标志,以查看该文件是为哪个平台构建的。 有关结构的更多信息,请参阅 WinNT.h。
Here's a C++ MFC console application that writes out the file header information. You can check the machine type (IMAGE_FILE_HEADER Machine member) or the IMAGE_FILE_32BIT_MACHINE flag in the Characteristics to see what platform the file is built for. See WinNT.h for more info on the structures.
这是我自己的实现,它有更多的检查,并且总是返回结果。
使用方法:
这里使用的枚举值是从 pe.go . 这样做的原因是,对于“go”的每个二进制发行版,程序集中必须具有正确的标志,以使其通过操作系统“你可以在这里运行吗?” 查看。 由于“go”是跨平台的(所有平台),因此它是获取此信息的良好基础。 这些信息可能还有其他来源,但它们似乎深深地嵌套在 google ca-ca 中,需要 Google-fu 中的 10 段黑带才能定位。
Here is my own implementation of this which has several more checks in place and always returns a result.
How to use :
For the enum values used here, they were obtained from pe.go . The reason why this works is that for each binary ditribution of 'go' must have the correct flag in the assembly to let it pass the operating systems 'can you run here ?' check. Since 'go' is cross platform (all platforms), it is a good base to get this information. There are probably other sources for this information, but they seem to be nested knee-deep in google ca-ca requiring a 10th dan black-belt in Google-fu to locate.
这是使用 C/C++ 作为独立工具的另一个解决方案,可以根据您的需要进行调整:
Here's another solution using C/C++ as a standalone tool, ready to be adapted to whatever you need: