C# 如何查找本机 DLL 文件是编译为 x64 还是 x86?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/480696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to find if a native DLL file is compiled as x64 or x86?
提问by Ohad Horesh
I want to determine if a native assembly is complied as x64 or x86 from a managed code application (C#).
我想确定本机程序集是否从托管代码应用程序 ( C#)编译为 x64 或 x86 。
I think it must be somewhere in the PE header since the OS loader needs to know this information, but I couldn't find it. Of course I prefer to do it in managed code, but if it necessary, I can use native C++.
我认为它必须在 PE 标头中的某个位置,因为操作系统加载程序需要知道此信息,但我找不到它。当然我更喜欢用托管代码来做,但如果有必要,我可以使用原生 C++。
回答by Steven Behnke
Apparently you can find it in the header of the portable executable. The corflags.exe utility is able to show you whether or not it targets x64. Hopefully this helps you find more information about it.
显然,您可以在可移植可执行文件的标题中找到它。corflags.exe 实用程序能够显示它是否面向 x64。希望这可以帮助您找到有关它的更多信息。
回答by Jacek ?awrynowicz
64-bit binaries are stored in PE32+ format. Try reading http://www.masm32.com/board/index.php?action=dlattach;topic=6687.0;id=3486
64 位二进制文件以 PE32+ 格式存储。尝试阅读http://www.masm32.com/board/index.php?action=dlattach;topic=6687.0;id=3486
回答by ShuggyCoUk
For an unmanaged DLL file, you need to first check if it is a 16-bit DLL file (hopefully not).
Then check the IMAGE\_FILE_HEADER.Machine
field.
对于非托管 DLL 文件,您需要首先检查它是否是 16 位 DLL 文件(希望不是)。然后检查IMAGE\_FILE_HEADER.Machine
字段。
Someone elsetook the time to work this out already, so I will just repeat here:
其他人已经花时间解决了这个问题,所以我在这里重复一遍:
To distinguish between a 32-bit and 64-bit PE file, you should check IMAGE_FILE_HEADER.Machine field. Based on the Microsoft PE and COFF specification below, I have listed out all the possible values for this field: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v8.doc
IMAGE_FILE_MACHINE_UNKNOWN 0x0 The contents of this field are assumed to be applicable to any machine type
IMAGE_FILE_MACHINE_AM33 0x1d3 Matsushita AM33
IMAGE_FILE_MACHINE_AMD64 0x8664 x64
IMAGE_FILE_MACHINE_ARM 0x1c0 ARM little endian
IMAGE_FILE_MACHINE_EBC 0xebc EFI byte code
IMAGE_FILE_MACHINE_I386 0x14c Intel 386 or later processors and compatible processors
IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium processor family
IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R little endian
IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16
IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS with FPU
IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 with FPU
IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC little endian
IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC with floating point support
IMAGE_FILE_MACHINE_R4000 0x166 MIPS little endian
IMAGE_FILE_MACHINE_SH3 0x1a2 Hitachi SH3
IMAGE_FILE_MACHINE_SH3DSP 0x1a3 Hitachi SH3 DSP
IMAGE_FILE_MACHINE_SH4 0x1a6 Hitachi SH4
IMAGE_FILE_MACHINE_SH5 0x1a8 Hitachi SH5
IMAGE_FILE_MACHINE_THUMB 0x1c2 Thumb
IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS little-endian WCE v2
Yes, you may check IMAGE_FILE_MACHINE_AMD64|IMAGE_FILE_MACHINE_IA64 for 64bit and IMAGE_FILE_MACHINE_I386 for 32bit.
要区分 32 位和 64 位 PE 文件,您应该检查 IMAGE_FILE_HEADER.Machine 字段。基于下面的 Microsoft PE 和 COFF 规范,我列出了该字段的所有可能值:http: //download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/ pecoff_v8.doc
IMAGE_FILE_MACHINE_UNKNOWN 0x0 该字段的内容假定适用于任何机器类型
IMAGE_FILE_MACHINE_AM33 0x1d3 松下 AM33
IMAGE_FILE_MACHINE_AMD64 0x8664 x64
IMAGE_FILE_MACHINE_ARM 0x1c0 ARM 小端
IMAGE_FILE_MACHINE_EBC 0xebc EFI 字节码
IMAGE_FILE_MACHINE_I386 0x14c Intel 386 或更高版本处理器和兼容处理器
IMAGE_FILE_MACHINE_IA64 0x200 英特尔安腾处理器家族
IMAGE_FILE_MACHINE_M32R 0x9041 三菱 M32R 小端
IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16
IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS 带 FPU
IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 带 FPU
IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC 小端
IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 具有浮点支持的 Power PC
IMAGE_FILE_MACHINE_R4000 0x166 MIPS 小端
IMAGE_FILE_MACHINE_SH3 0x1a2 日立 SH3
IMAGE_FILE_MACHINE_SH3DSP 0x1a3 日立 SH3 DSP
IMAGE_FILE_MACHINE_SH4 0x1a6 日立 SH4
IMAGE_FILE_MACHINE_SH5 0x1a8 日立 SH5
IMAGE_FILE_MACHINE_THUMB 0x1c2 拇指
IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS 小端 WCE v2
是的,您可以检查 IMAGE_FILE_MACHINE_AMD64|IMAGE_FILE_MACHINE_IA64 为 64 位和 IMAGE_FILE_MACHINE_I386 为 32 位。
回答by yoyoyoyosef
You can find a C# sample implementation herefor the IMAGE_FILE_HEADER
solution
你可以找到一个在这里C#示例实现的IMAGE_FILE_HEADER
解决方案
回答by BLogan
There is an easy way to do this with CorFlags. Open the Visual Studio Command Prompt and type "corflags [your assembly]". You'll get something like this:
使用CorFlags有一种简单的方法可以做到这一点。打开 Visual Studio 命令提示符并键入“corflags [你的程序集]”。你会得到这样的东西:
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC>corflags "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll"
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 3.5.21022.8 Copyright (c) Microsoft Corporation. All rights reserved.
Version : v2.0.50727 CLR Header: 2.5 PE : PE32 CorFlags : 24 ILONLY : 0 32BIT : 0 Signed : 1
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC>corflags "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll"
Microsoft (R) .NET Framework CorFlags 转换工具。版本 3.5.21022.8 版权所有 (c) Microsoft Corporation。版权所有。
版本:v2.0.50727 CLR 标头:2.5 PE:PE32 CorFlags:24 ILONLY:0 32BIT:0 签名:1
You're looking at PE and 32BIT specifically.
您正在专门研究 PE 和 32BIT。
Any CPU:
PE: PE32
32BIT: 0x86:
PE: PE32
32BIT: 1x64:
PE: PE32+
32BIT: 0
任何 CPU:
PE:PE32
32位:0x86:
PE:PE32
32BIT:1x64:
PE:PE32+
32BIT:0
回答by Mark McDonald
You can use DUMPBINtoo. Use the /headers
or /all
flag and its the first file header listed.
您也可以使用DUMPBIN。使用/headers
or/all
标志及其列出的第一个文件头。
dumpbin /headers cv210.dll
64-bit
64 位
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-bit
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
'find' can make life slightly easier:
'find' 可以让生活稍微轻松一点:
dumpbin /headers cv210.dll |find "machine"
8664 machine (x64)
回答by Jason Larke
The Magic
field of the IMAGE_OPTIONAL_HEADER
(though there is nothing optional about the header in Windows executable images (DLL/EXE files)) will tell you the architecture of the PE.
的Magic
字段IMAGE_OPTIONAL_HEADER
(尽管 Windows 可执行映像(DLL/EXE 文件)中的标头没有任何可选内容)将告诉您 PE 的体系结构。
Here's an example of grabbing the architecture from a file.
这是从文件中获取架构的示例。
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 "PE0x10b - PE32
0x20b - PE32+
#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;
}
" 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();
}
}
The only two architecture constants at the moment are:
目前仅有的两个架构常量是:
#Description C# compiler switch PE type machine corflags
#MSIL /platform:anycpu (default) PE32 x86 ILONLY
#MSIL 32 bit pref /platform:anycpu32bitpreferred PE32 x86 ILONLY | 32BITREQUIRED | 32BITPREFERRED
#x86 managed /platform:x86 PE32 x86 ILONLY | 32BITREQUIRED
#x86 mixed n/a PE32 x86 32BITREQUIRED
#x64 managed /platform:x64 PE32+ x64 ILONLY
#x64 mixed n/a PE32+ x64
#ARM managed /platform:arm PE32 ARM ILONLY
#ARM mixed n/a PE32 ARM
Cheers
干杯
UPDATEIt's been a while since I posted this answer, yet I still see that it gets a few upvotes now and again so I figured it was worth updating. I wrote a way to get the architecture of a Portable Executable
image, which also checks to see if it was compiled as AnyCPU
. Unfortunately the answer is in C++, but it shouldn't be too hard to port to C# if you have a few minutes to look up the structures in WinNT.h
. If people are interested I'll write a port in C#, but unless people actually want it I wont spend much time stressing about it.
更新我发布这个答案已经有一段时间了,但我仍然看到它时不时地得到一些赞成,所以我认为它值得更新。我编写了一种获取Portable Executable
图像架构的方法,该方法还会检查它是否被编译为AnyCPU
. 不幸的是,答案是在 C++ 中,但如果您有几分钟时间在WinNT.h
. 如果人们有兴趣,我会用 C# 编写一个端口,但除非人们真的想要它,否则我不会花太多时间来强调它。
function GetActualAddressFromRVA($st, $sec, $numOfSec, $dwRVA)
{
[System.UInt32] $dwRet = 0;
for($j = 0; $j -lt $numOfSec; $j++)
{
$nextSectionOffset = $sec + 40*$j;
$VirtualSizeOffset = 8;
$VirtualAddressOffset = 12;
$SizeOfRawDataOffset = 16;
$PointerToRawDataOffset = 20;
$Null = @(
$curr_offset = $st.BaseStream.Seek($nextSectionOffset + $VirtualSizeOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $VirtualSize = $b.ReadUInt32();
[System.UInt32] $VirtualAddress = $b.ReadUInt32();
[System.UInt32] $SizeOfRawData = $b.ReadUInt32();
[System.UInt32] $PointerToRawData = $b.ReadUInt32();
if ($dwRVA -ge $VirtualAddress -and $dwRVA -lt ($VirtualAddress + $VirtualSize)) {
$delta = $VirtualAddress - $PointerToRawData;
$dwRet = $dwRVA - $delta;
return $dwRet;
}
);
}
return $dwRet;
}
function Get-Bitness2([System.String]$path, $showLog = $false)
{
$Obj = @{};
$Obj.Result = '';
$Obj.Error = $false;
$Obj.Log = @(Split-Path -Path $path -Leaf -Resolve);
$b = new-object System.IO.BinaryReader([System.IO.File]::Open($path,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read, [System.IO.FileShare]::Read));
$curr_offset = $b.BaseStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin)
[System.Int32] $peOffset = $b.ReadInt32();
$Obj.Log += 'peOffset ' + "{0:X0}" -f $peOffset;
$curr_offset = $b.BaseStream.Seek($peOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $peHead = $b.ReadUInt32();
if ($peHead -ne 0x00004550) {
$Obj.Error = $true;
$Obj.Result = 'Bad Image Format';
$Obj.Log += 'cannot determine file type (not x64/x86/ARM) - exit with error';
};
if ($Obj.Error)
{
$b.Close();
Write-Host ($Obj.Log | Format-List | Out-String);
return $false;
};
[System.UInt16] $machineType = $b.ReadUInt16();
$Obj.Log += 'machineType ' + "{0:X0}" -f $machineType;
[System.UInt16] $numOfSections = $b.ReadUInt16();
$Obj.Log += 'numOfSections ' + "{0:X0}" -f $numOfSections;
if (($machineType -eq 0x8664) -or ($machineType -eq 0x200)) { $Obj.Log += 'machineType: x64'; }
elseif ($machineType -eq 0x14c) { $Obj.Log += 'machineType: x86'; }
elseif ($machineType -eq 0x1c0) { $Obj.Log += 'machineType: ARM'; }
else{
$Obj.Error = $true;
$Obj.Log += 'cannot determine file type (not x64/x86/ARM) - exit with error';
};
if ($Obj.Error) {
$b.Close();
Write-Output ($Obj.Log | Format-List | Out-String);
return $false;
};
$curr_offset = $b.BaseStream.Seek($peOffset+20, [System.IO.SeekOrigin]::Begin);
[System.UInt16] $sizeOfPeHeader = $b.ReadUInt16();
$coffOffset = $peOffset + 24;#PE header size is 24 bytes
$Obj.Log += 'coffOffset ' + "{0:X0}" -f $coffOffset;
$curr_offset = $b.BaseStream.Seek($coffOffset, [System.IO.SeekOrigin]::Begin);#+24 byte magic number
[System.UInt16] $pe32 = $b.ReadUInt16();
$clr20headerOffset = 0;
$flag32bit = $false;
$Obj.Log += 'pe32 magic number: ' + "{0:X0}" -f $pe32;
$Obj.Log += 'size of optional header ' + ("{0:D0}" -f $sizeOfPeHeader) + " bytes";
#COMIMAGE_FLAGS_ILONLY =0x00000001,
#COMIMAGE_FLAGS_32BITREQUIRED =0x00000002,
#COMIMAGE_FLAGS_IL_LIBRARY =0x00000004,
#COMIMAGE_FLAGS_STRONGNAMESIGNED =0x00000008,
#COMIMAGE_FLAGS_NATIVE_ENTRYPOINT =0x00000010,
#COMIMAGE_FLAGS_TRACKDEBUGDATA =0x00010000,
#COMIMAGE_FLAGS_32BITPREFERRED =0x00020000,
$COMIMAGE_FLAGS_ILONLY = 0x00000001;
$COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
$COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000;
$offset = 96;
if ($pe32 -eq 0x20b) {
$offset = 112;#size of COFF header is bigger for pe32+
}
$clr20dirHeaderOffset = $coffOffset + $offset + 14*8;#clr directory header offset + start of section number 15 (each section is 8 byte long);
$Obj.Log += 'clr20dirHeaderOffset ' + "{0:X0}" -f $clr20dirHeaderOffset;
$curr_offset = $b.BaseStream.Seek($clr20dirHeaderOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $clr20VirtualAddress = $b.ReadUInt32();
[System.UInt32] $clr20Size = $b.ReadUInt32();
$Obj.Log += 'clr20VirtualAddress ' + "{0:X0}" -f $clr20VirtualAddress;
$Obj.Log += 'clr20SectionSize ' + ("{0:D0}" -f $clr20Size) + " bytes";
if ($clr20Size -eq 0) {
if ($machineType -eq 0x1c0) { $Obj.Result = 'ARM native'; }
elseif ($pe32 -eq 0x10b) { $Obj.Result = '32-bit native'; }
elseif($pe32 -eq 0x20b) { $Obj.Result = '64-bit native'; }
$b.Close();
if ($Obj.Result -eq '') {
$Obj.Error = $true;
$Obj.Log += 'Unknown type of file';
}
else {
if ($showLog) { Write-Output ($Obj.Log | Format-List | Out-String); };
return $Obj.Result;
}
};
if ($Obj.Error) {
$b.Close();
Write-Host ($Obj.Log | Format-List | Out-String);
return $false;
};
[System.UInt32]$sectionsOffset = $coffOffset + $sizeOfPeHeader;
$Obj.Log += 'sectionsOffset ' + "{0:X0}" -f $sectionsOffset;
$realOffset = GetActualAddressFromRVA $b $sectionsOffset $numOfSections $clr20VirtualAddress;
$Obj.Log += 'real IMAGE_COR20_HEADER offset ' + "{0:X0}" -f $realOffset;
if ($realOffset -eq 0) {
$Obj.Error = $true;
$Obj.Log += 'cannot find COR20 header - exit with error';
$b.Close();
return $false;
};
if ($Obj.Error) {
$b.Close();
Write-Host ($Obj.Log | Format-List | Out-String);
return $false;
};
$curr_offset = $b.BaseStream.Seek($realOffset + 4, [System.IO.SeekOrigin]::Begin);
[System.UInt16] $majorVer = $b.ReadUInt16();
[System.UInt16] $minorVer = $b.ReadUInt16();
$Obj.Log += 'IMAGE_COR20_HEADER version ' + ("{0:D0}" -f $majorVer) + "." + ("{0:D0}" -f $minorVer);
$flagsOffset = 16;#+16 bytes - flags field
$curr_offset = $b.BaseStream.Seek($realOffset + $flagsOffset, [System.IO.SeekOrigin]::Begin);
[System.UInt32] $flag32bit = $b.ReadUInt32();
$Obj.Log += 'CorFlags: ' + ("{0:X0}" -f $flag32bit);
#Description C# compiler switch PE type machine corflags
#MSIL /platform:anycpu (default) PE32 x86 ILONLY
#MSIL 32 bit pref /platform:anycpu32bitpreferred PE32 x86 ILONLY | 32BITREQUIRED | 32BITPREFERRED
#x86 managed /platform:x86 PE32 x86 ILONLY | 32BITREQUIRED
#x86 mixed n/a PE32 x86 32BITREQUIRED
#x64 managed /platform:x64 PE32+ x64 ILONLY
#x64 mixed n/a PE32+ x64
#ARM managed /platform:arm PE32 ARM ILONLY
#ARM mixed n/a PE32 ARM
$isILOnly = ($flag32bit -band $COMIMAGE_FLAGS_ILONLY) -eq $COMIMAGE_FLAGS_ILONLY;
$Obj.Log += 'ILONLY: ' + $isILOnly;
if ($machineType -eq 0x1c0) {#if ARM
if ($isILOnly) { $Obj.Result = 'ARM managed'; }
else { $Obj.Result = 'ARM mixed'; }
}
elseif ($pe32 -eq 0x10b) {#pe32
$is32bitRequired = ($flag32bit -band $COMIMAGE_FLAGS_32BITREQUIRED) -eq $COMIMAGE_FLAGS_32BITREQUIRED;
$is32bitPreffered = ($flag32bit -band $COMIMAGE_FLAGS_32BITPREFERRED) -eq $COMIMAGE_FLAGS_32BITPREFERRED;
$Obj.Log += '32BIT: ' + $is32bitRequired;
$Obj.Log += '32BIT PREFFERED: ' + $is32bitPreffered
if ($is32bitRequired -and $isILOnly -and $is32bitPreffered) { $Obj.Result = 'AnyCpu 32bit-preffered'; }
elseif ($is32bitRequired -and $isILOnly -and !$is32bitPreffered){ $Obj.Result = 'x86 managed'; }
elseif (!$is32bitRequired -and !$isILOnly -and $is32bitPreffered) { $Obj.Result = 'x86 mixed'; }
elseif ($isILOnly) { $Obj.Result = 'AnyCpu'; }
}
elseif ($pe32 -eq 0x20b) {#pe32+
if ($isILOnly) { $Obj.Result = 'x64 managed'; }
else { $Obj.Result = 'x64 mixed'; }
}
$b.Close();
if ($showLog) { Write-Host ($Obj.Log | Format-List | Out-String); }
if ($Obj.Result -eq ''){ return 'Unknown type of file';};
$flags = '';
if ($isILOnly) {$flags += 'ILONLY';}
if ($is32bitRequired) {
if ($flags -ne '') {$flags += ' | ';}
$flags += '32BITREQUIRED';
}
if ($is32bitPreffered) {
if ($flags -ne '') {$flags += ' | ';}
$flags += '32BITPREFERRED';
}
if ($flags -ne '') {$flags = ' (' + $flags +')';}
return $Obj.Result + $flags;
}
The function accepts a pointer to an in-memory PE image (so you can choose your poison on how to get it their; memory-mapping or reading the whole thing into memory...whatever).
该函数接受一个指向内存中 PE 映像的指针(因此您可以选择如何获取它的毒药;内存映射或将整个内容读入内存......无论如何)。
回答by Philip Mc Laughlin
回答by sqladmin
I rewrote c++ solutionin first answer in powershell script. Script can determine this types of .exe and .dll files:
我在 powershell 脚本的第一个答案中重写了c++ 解决方案。脚本可以确定此类 .exe 和 .dll 文件:
#$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;
this solution has some advantages over corflags.exe and loading assembly via Assembly.Load in C# - you will never get BadImageFormatException or message about invalid header.
此解决方案比 corflags.exe 和通过 C# 中的 Assembly.Load 加载程序集具有一些优势 - 您永远不会收到 BadImageFormatException 或有关无效标头的消息。
##代码##usage example:
用法示例:
##代码##you can omit second parameter if you don't need to see details
如果不需要查看详细信息,可以省略第二个参数
回答by ohgodnotanotherone
A quick and probably dirty way to do it is described here: https://superuser.com/a/889267. You open the DLL in an editor and check the first characters after the "PE" sequence.
这里描述了一种快速且可能肮脏的方法:https: //superuser.com/a/889267。在编辑器中打开 DLL 并检查“PE”序列后的第一个字符。