네이티브 DLL 파일이 x64 또는 x86으로 컴파일되었는지 확인하는 방법은 무엇입니까?


133

네이티브 어셈블리가 관리 코드 응용 프로그램 ( C # ) 에서 x64 또는 x86으로 준수되는지 확인하고 싶습니다 .

OS 로더 가이 정보를 알아야하기 때문에 PE 헤더의 어딘가에 있어야한다고 생각하지만 찾을 수 없었습니다. 물론 관리되는 코드에서 수행하는 것을 선호하지만 필요한 경우 기본 C ++을 사용할 수 있습니다.


분명히, 해당 dll은 .Net 어셈블리입니까? 당신은 게시물의 제목으로 네이티브 DLL을 말하지만 설명에서 네이티브 어셈블리를 말합니다 ... 여전히이 게시물을 09에서 적극적으로보고 있다면 :)
— Vikas Gupta

1
당신은이 일을 확인 할 수 있습니다 : 체크하면-관리되지 않는-DLL은-IS-32 비트 또는 64 비트 .
— Matt

답변:


143

DUMPBIN 도 사용할 수 있습니다 . /headers또는 /all플래그와 나열된 첫 번째 파일 헤더를 사용하십시오 .

dumpbin /headers cv210.dll

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 비트

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

'찾기'는 삶을 조금 더 쉽게 만들 수 있습니다.

dumpbin /headers cv210.dll |find "machine"
        8664 machine (x64)

4
약간 더 사용자 친화적 인;)
— Ant

4
DUMPBIN은 .NET EXE에서 작동하지 않습니다. DUMPBIN이 32 비트 ( "14C 시스템 (x86)")라고하는 64 비트 .NET EXE가 있지만 corflags는 Any CPU ( "PE : PE32, 32BIT : 0")라고 말합니다. Dependency Walker는 또한 그것을 잘못 진단합니다.
— Pierre

2
그것은 필요했다 mspdb100.dll:(
— Dmitry

1
@ Altaveron 나는 같은 문제가 있었지만 DLL 파일 mspdb100.dll을있는 폴더 에 복사하여 해결했습니다 dumpbin.exe. DUMPBIN그 후에 실행할 수 있습니다. 나를 위해 EXE는에 <Visual Studio Install folder>\VC\bin있고 DLL은에 <Visual Studio Install folder>\Common7\IDE있습니다.
— ADTC

DUMPBIN은 Visual Studio가 설치된 사용자를 위해 Visual Studio 명령 프롬프트에서 사용할 수 있습니다.
— Alan Macdonald

55

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 변환 도구. 버전 3.5.21022.8 저작권 (c) Microsoft Corporation. 판권 소유.

버전 : v2.0.50727 CLR 헤더 : 2.5 PE : PE32 CorFlags : 24 ILONLY : 0 32BIT : 0 서명 : 1

PE와 32BIT를 구체적으로보고 있습니다.

  • 모든 CPU :

    PE : PE32 32
    비트 : 0

  • x86 :

    PE : PE32 32
    비트 : 1

  • x64 :

    PE : PE32 +
    32BIT : 0


18
@BLogan 위의 Steven Behnke에 대한 내 의견을 봐야합니다. corflags 유틸리티에 대해 알고 있지만 기본 어셈블리에서는 작동하지 않습니다.
— Ohad Horesh

7
Corflags 출력 결과는 이후 버전 (Windows SDK 8 이상)에서 변경되었습니다. 이제 32BIT 대신 32BITREQUIRED 및 32BITPREFERRED가 있습니다. C : \ Program Files (x86) \ Windows Kits \ 8.0 \ Include \ um \ CorHdr.h에있는 CorHdr.h의 설명을 참조하십시오. 내가 말할 수있는 32BITREQUIRED는 32BIT를 대체합니다. 이 질문에 대한 답변도 참조하십시오 .
— Wes

37

이 트릭 은 작동하며 메모장 만 필요합니다.

메모장과 같은 텍스트 편집기를 사용하여 dll 파일을 열고 문자열이 처음 나타나는 것을 찾으십시오 PE. 다음 문자는 dll이 32 비트인지 64 비트인지를 정의합니다.

32 비트 :

PE  L

64 비트 :

PE  d†

25

Magic의 필드 IMAGE_OPTIONAL_HEADER당신에게 PE의 구조를 말할 것이다 (하지만이 윈도우 실행 이미지 (DLL / EXE 파일)의 헤더에 대한 옵션 아무 것도 없다).

다음은 파일에서 아키텍처를 가져 오는 예입니다.

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 ++에 있지만에서 구조를 조회하는 데 몇 분이 걸리더라도 C #으로 포팅하기가 너무 어렵지 않아야합니다 WinNT.h. 사람들이 관심이 있다면 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 이미지에 대한 포인터를 허용합니다 (따라서 독을 선택하는 방법; 메모리 매핑 또는 전체 내용을 메모리로 읽는 방법 등).


매우 흥미롭지 만 Any CPU로 컴파일 된 응용 프로그램이 있으면 결과는 0x10B입니다. 내 응용 프로그램이 x64 시스템에서 실행되기 때문에 이것은 잘못된 것입니다. 확인할 다른 플래그가 있습니까?
— 사무엘

3
AnyCPU의 의미는 다음과 같습니다. AnyCPU이므로 32 비트와의 하위 호환성을 위해 PE 헤더에 0x10B로 표시됩니다. 그와 32 비트의 차이점을 확인하려면 32BITPE에서 CorFlags가 깃발을 가져 오는 위치를 알아야합니다. 머리 꼭대기를 알지 못합니다.
— Jason

@JasonLarke Google 검색에서 여기에 착륙했으며 코드 스 니펫이 도움이되었습니다. 많은 감사합니다!
— Parag Doke 2013

@Samuel AnyCPU 플래그를 확인하도록 업데이트되었습니다.
— Jason Larke 2013

C # 코드는 32 비트 어셈블리를 확인할 때 64 비트 프로세스에서 작동합니까? 예를 들어, Module.GetPEKind msdn.microsoft.com/en-us/library/… 실패
— Kiquenet

14

관리되지 않는 DLL 파일의 경우 먼저 16 비트 DLL 파일인지 확인해야합니다 (권장하지 않음). 그런 다음 IMAGE\_FILE_HEADER.Machine필드를 확인하십시오 .

다른 누군가 가 이미이 문제를 해결하는 데 시간 이 걸렸으므로 여기서 반복 할 것입니다.

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 Intel Itanium 프로세서 제품군

IMAGE_FILE_MACHINE_M32R 0x9041 미쓰비시 M32R 리틀 엔디안

IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

FPU가있는 IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS

FPU 포함 IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16

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 Hitachi SH3 DSP

IMAGE_FILE_MACHINE_SH4 0x1a6 히타치 SH4

IMAGE_FILE_MACHINE_SH5 0x1a8 히타치 SH5

IMAGE_FILE_MACHINE_THUMB 0x1c2 Thumb

IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS 리틀 엔디안 WCE v2

예, IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64는 64 비트이고 IMAGE_FILE_MACHINE_I386은 32 비트입니다.


당신의 두 번째 링크는 죽었습니다 : s
— gpalex



3

HxD 와 같은 16 진 편집기로 dll을 엽니 다.

9 번째 줄에 "dt"가 있으면 64 비트입니다.

"L"이있는 경우 9 번째 줄에서는 32 비트입니다.


"dt"및 "L"을 찾을 수 없습니다. "Far Manager"HEX 뷰어에서.
— Dmitry

d로 표시됩니다. 그리고 L.
— Zax

1

powershell 스크립트의 첫 번째 답변에서 C ++ 솔루션 을 다시 작성했습니다 . 스크립트는이 유형의 .exe 및 .dll 파일을 결정할 수 있습니다.

#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  

이 솔루션은 corflags.exe 및 C #에서 Assembly.Load를 통해 어셈블리를로드하는 것보다 몇 가지 장점이 있습니다. 잘못된 이미지에 대한 BadImageFormatException 또는 메시지가 표시되지 않습니다.

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;
}

사용 예 :

#$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;

세부 사항을 볼 필요가 없으면 두 번째 매개 변수를 생략 할 수 있습니다



0

분명히 휴대용 실행 파일의 헤더에서 찾을 수 있습니다. corflags.exe 유틸리티는 x64를 대상으로하는지 여부를 표시 할 수 있습니다. 이 정보가 더 많은 정보를 찾는 데 도움이되기를 바랍니다.


3
고맙지 만 Steven하지만 corflags.exe는 기본 어셈블리에서 작동하지 않습니다.
— Ohad Horesh

1
Windows 10 :>corflags libzmq.dll \n\n ... corflags : error CF008 : The specified file does not have a valid managed header
— Grault
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.