Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file cv210.dll
PE signature found
File Type: DLL
FILE HEADER VALUES
8664 machine (x64)
6 number of sections
4BBAB813 time date stamp Tue Apr 06 12:26:59 2010
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
2022 characteristics
Executable
Application can handle large (>2GB) addresses
DLL
32位
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file acrdlg.dll
PE signature found
File Type: DLL
FILE HEADER VALUES
14C machine (x86)
5 number of sections
467AFDD2 time date stamp Fri Jun 22 06:38:10 2007
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2306 characteristics
Executable
Line numbers stripped
32 bit word machine
Debug information stripped
DLL
IMAGE_OPTIONAL_HEADER的 Magic字段(尽管在 Windows 可执行图像(DLL/EXE 文件)中头部没有任何可选项)将告诉您 PE 的体系结构。
下面是一个从文件中获取体系结构的示例。
public static ushort GetImageArchitecture(string filepath) {
using (var stream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (var reader = new System.IO.BinaryReader(stream)) {
//check the MZ signature to ensure it's a valid Portable Executable image
if (reader.ReadUInt16() != 23117)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
// seek to, and read, e_lfanew then advance the stream to there (start of NT header)
stream.Seek(0x3A, System.IO.SeekOrigin.Current);
stream.Seek(reader.ReadUInt32(), System.IO.SeekOrigin.Begin);
// Ensure the NT header is valid by checking the "PE\0\0" signature
if (reader.ReadUInt32() != 17744)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
// seek past the file header, then read the magic number from the optional header
stream.Seek(20, System.IO.SeekOrigin.Current);
return reader.ReadUInt16();
}
}
目前仅有的两个架构常量是:
0x10b - PE32
0x20b - PE32+
干杯
更新
我已经有一段时间没有发布这个答案了,但是我仍然看到它时不时得到一些赞同,所以我觉得值得更新。我写了一个方法来获得一个 Portable Executable映像的架构,它还检查它是否被编译为 AnyCPU。不幸的是,答案是在 C + + 中,但是如果您有几分钟时间查找 WinNT.h中的结构,那么移植到 C # 应该不会太难。如果人们感兴趣,我会用 C # 编写一个端口,但是除非人们真的想要它,否则我不会花太多时间去强调它。
#include <Windows.h>
#define MKPTR(p1,p2) ((DWORD_PTR)(p1) + (DWORD_PTR)(p2))
typedef enum _pe_architecture {
PE_ARCHITECTURE_UNKNOWN = 0x0000,
PE_ARCHITECTURE_ANYCPU = 0x0001,
PE_ARCHITECTURE_X86 = 0x010B,
PE_ARCHITECTURE_x64 = 0x020B
} PE_ARCHITECTURE;
LPVOID GetOffsetFromRva(IMAGE_DOS_HEADER *pDos, IMAGE_NT_HEADERS *pNt, DWORD rva) {
IMAGE_SECTION_HEADER *pSecHd = IMAGE_FIRST_SECTION(pNt);
for(unsigned long i = 0; i < pNt->FileHeader.NumberOfSections; ++i, ++pSecHd) {
// Lookup which section contains this RVA so we can translate the VA to a file offset
if (rva >= pSecHd->VirtualAddress && rva < (pSecHd->VirtualAddress + pSecHd->Misc.VirtualSize)) {
DWORD delta = pSecHd->VirtualAddress - pSecHd->PointerToRawData;
return (LPVOID)MKPTR(pDos, rva - delta);
}
}
return NULL;
}
PE_ARCHITECTURE GetImageArchitecture(void *pImageBase) {
// Parse and validate the DOS header
IMAGE_DOS_HEADER *pDosHd = (IMAGE_DOS_HEADER*)pImageBase;
if (IsBadReadPtr(pDosHd, sizeof(pDosHd->e_magic)) || pDosHd->e_magic != IMAGE_DOS_SIGNATURE)
return PE_ARCHITECTURE_UNKNOWN;
// Parse and validate the NT header
IMAGE_NT_HEADERS *pNtHd = (IMAGE_NT_HEADERS*)MKPTR(pDosHd, pDosHd->e_lfanew);
if (IsBadReadPtr(pNtHd, sizeof(pNtHd->Signature)) || pNtHd->Signature != IMAGE_NT_SIGNATURE)
return PE_ARCHITECTURE_UNKNOWN;
// First, naive, check based on the 'Magic' number in the Optional Header.
PE_ARCHITECTURE architecture = (PE_ARCHITECTURE)pNtHd->OptionalHeader.Magic;
// If the architecture is x86, there is still a possibility that the image is 'AnyCPU'
if (architecture == PE_ARCHITECTURE_X86) {
IMAGE_DATA_DIRECTORY comDirectory = pNtHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
if (comDirectory.Size) {
IMAGE_COR20_HEADER *pClrHd = (IMAGE_COR20_HEADER*)GetOffsetFromRva(pDosHd, pNtHd, comDirectory.VirtualAddress);
// Check to see if the CLR header contains the 32BITONLY flag, if not then the image is actually AnyCpu
if ((pClrHd->Flags & COMIMAGE_FLAGS_32BITREQUIRED) == 0)
architecture = PE_ARCHITECTURE_ANYCPU;
}
}
return architecture;
}
该函数接受一个指向内存中 PE 映像的指针(因此您可以选择如何获得它们的; 内存映射或将整个内存读入内存... ... 等等)。
#$filePath = "C:\Windows\SysWOW64\regedit.exe";#32 bit native on 64bit windows
$filePath = "C:\Windows\regedit.exe";#64 bit native on 64bit windows | should be 32 bit native on 32bit windows
Get-Bitness2 $filePath $true;
function [simplifiedInfo] = GetPortableExecutableSimplifiedInfo(filename)
%[
% Checking arguments
if (nargin <1), error('MATLAB:minrhs', 'Not enough input argments.'); end
% Initializing simplified info
simplifiedInfo.Kind = 'Other';
simplifiedInfo.CodeType = 'Other';
simplifiedInfo.Platform = 'Other';
% Obtaining raw info
[rawInfo, PEConstants] = GetPortableExecutableRawInfo(filename);
% Determining 'Kind' of PE
if (isfield(rawInfo, 'PEOptionalHeader') && (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_EXECUTABLE_IMAGE))
if (rawInfo.COFFHeader.Characteristics.IMAGE_FILE_DLL)
simplifiedInfo.Kind = 'Library';
else
simplifiedInfo.Kind = 'Executable';
end
else
% No optional header or no IMAGE_FILE_EXECUTABLE_IMAGE flag ...
% Maybe just .obj or other thing
simplifiedInfo.Kind = 'Other';
end
% Determining 'CodeType'
% NB: 'COR20Header' is present for MSIL code, but not for native code
if (isfield(rawInfo, 'COR20Header'))
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_ILONLY)
simplifiedInfo.CodeType = 'Managed';
else
simplifiedInfo.CodeType = 'Mixed';
end
else
simplifiedInfo.CodeType = 'Native';
end
% Determining platform
if (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_AMD64)
simplifiedInfo.Platform = 'x64';
elseif (rawInfo.COFFHeader.Machine == PEConstants.IMAGE_FILE_MACHINE_I386)
if (isfield(rawInfo, 'COR20Header'))
% PE contains MSIL code, need more checks
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITREQUIRED)
if (rawInfo.COR20Header.Flags.COMIMAGE_FLAGS_32BITPREFERRED)
simplifiedInfo.Platform = 'x32Preferred';
else
simplifiedInfo.Platform = 'x32';
end
else
simplifiedInfo.Platform = 'AnyCpu';
end
else
% This is native code so ...
simplifiedInfo.Platform = 'x32';
end
else
% ARM, ...
simplifiedInfo.Platform = 'Other';
end
%]
end