네이티브 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.