Jak sprawdzić, czy natywny plik DLL jest skompilowany jako x64 czy x86?

135

Chcę ustalić, czy natywny zestaw jest zgodny jako x64 lub x86 z aplikacji kodu zarządzanego ( C # ).

Myślę, że musi to być gdzieś w nagłówku PE, ponieważ moduł ładujący systemu operacyjnego musi znać te informacje, ale nie mogłem ich znaleźć. Oczywiście wolę to robić w kodzie zarządzanym, ale w razie potrzeby mogę użyć natywnego C ++.

Ohad Horesh
źródło
Żeby było jasne, dll, o którym mowa, jest również zestawem .Net? W tytule postu mówisz natywny DLL, ale w opisie natywny assembler ... jeśli nadal aktywnie patrzysz na ten post od 09 :)
Vikas Gupta
1
Możesz również sprawdzić ten: check-if-unmanaged-dll-is-32-bit-or-64-bit .
Matt

Odpowiedzi:

144

Możesz też użyć DUMPBIN . Użyj flagi /headerslub /alli jej pierwszego wymienionego nagłówka pliku.

dumpbin /headers cv210.dll

64-bitowy

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-bitowy

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

„znajdź” może nieco ułatwić życie:

dumpbin /headers cv210.dll |find "machine"
        8664 machine (x64)
Mark McDonald
źródło
4
Nieco bardziej przyjazny dla użytkownika;)
Ant
4
DUMPBIN nie działa dla plików .NET EXE. Mam 64-bitowy .NET EXE, o którym DUMPBIN mówi, że jest 32-bitowy („maszyna 14C (x86)”), ale corflags mówi, że to Dowolny procesor („PE: PE32, 32BIT: 0”). Dependency Walker również błędnie ją diagnozuje.
Pierre
2
Wymagało to mspdb100.dll:(
Dmitry
1
@Altaveron Miałem ten sam problem, ale rozwiązałem go, kopiując plik DLL mspdb100.dlldo folderu, w którym dumpbin.exesię znajduje. DUMPBINmoże biec po tym. Dla mnie <Visual Studio Install folder>\VC\binplik EXE jest pod adresem, a plik DLL jest pod adresem <Visual Studio Install folder>\Common7\IDE.
ADTC,
DUMPBIN jest dostępny z wiersza polecenia programu Visual Studio dla osób z zainstalowanym programem Visual Studio
Alan Macdonald
55

Z CorFlags można to łatwo zrobić . Otwórz wiersz polecenia programu Visual Studio i wpisz „corflags [twój zestaw]”. Otrzymasz coś takiego:

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. Wersja 3.5.21022.8 Copyright (c) Microsoft Corporation. Wszelkie prawa zastrzeżone.

Wersja: v2.0.50727 CLR Nagłówek: 2.5 PE: PE32 CorFlags: 24 ILONLY: 0 32BIT: 0 Podpis: 1

Patrzysz konkretnie na PE i 32BIT.

  • Dowolny procesor :

    PE: PE32
    32BIT: 0

  • x86 :

    PE: PE32
    32BIT: 1

  • x64:

    PE: PE32 +
    32BIT: 0

BLogan
źródło
19
@BLogan, powinieneś spojrzeć na mój komentarz do Stevena Behnke powyżej. Znam narzędzie corflags, ale nie działa na natywnych zespołach.
Ohad Horesh
7
Jakie dane wyjściowe Corflags zmieniły się w ostatnich wersjach (Windows SDK 8 lub nowszy). Teraz zamiast 32-BITOWEGO ma 32-BITOWE WYMAGANE i 32-BITOWE WYMAGANE. Zobacz opis w CorHdr.h, który znajduje się w C: \ Program Files (x86) \ Windows Kits \ 8.0 \ Include \ um \ CorHdr.h. Z tego co wiem, 32BITREQUIRED zastępuje 32BIT. Zobacz także odpowiedź na to pytanie .
Wes
39

Ta sztuczka działa i wymaga tylko Notatnika.

Otwórz plik dll za pomocą edytora tekstu (takiego jak Notatnik) i znajdź pierwsze wystąpienie ciągu PE. Poniższy znak określa, czy dll ma 32 czy 64 bity.

32 bity:

PE  L

64 bity:

PE  d†
Zanon
źródło
25

MagicDziedzina IMAGE_OPTIONAL_HEADER(choć nie ma nic opcjonalnie o nagłówku w systemie Windows (pliki wykonywalne zdjęć DLL / EXE)) powie architekturę PE.

Oto przykład pobierania architektury z pliku.

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

Obecnie jedyne dwie stałe architektury to:

0x10b - PE32
0x20b - PE32+

Twoje zdrowie

AKTUALIZACJA Minęło trochę czasu, odkąd opublikowałem tę odpowiedź, ale nadal widzę, że od czasu do czasu dostaje kilka pozytywnych głosów, więc pomyślałem, że warto to zaktualizować. Napisałem sposób na uzyskanie architektury Portable Executableobrazu, który również sprawdza, czy został skompilowany jako AnyCPU. Niestety odpowiedź jest w C ++, ale nie powinno być zbyt trudno przenieść się do C #, jeśli masz kilka minut na sprawdzenie struktur WinNT.h. Jeśli ludzie są zainteresowani, napiszę port w C #, ale jeśli ludzie tego nie chcą, nie spędzę zbyt wiele czasu na stresowaniu się tym.

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

Funkcja akceptuje wskaźnik do obrazu PE w pamięci (więc możesz wybrać swoją truciznę, jak ją zdobyć; mapowanie pamięci lub wczytywanie całości do pamięci ... cokolwiek).

Jason Larke
źródło
Bardzo interesujące, ale kiedy mam aplikację skompilowaną z dowolnym procesorem, wynik to 0x10B. To jest złe, ponieważ moja aplikacja działa w systemie x64. Czy jest jakaś inna flaga do sprawdzenia?
Samuel
3
AnyCPU oznacza po prostu: AnyCPU, więc jest wymieniony jako 0x10B w nagłówku PE, aby zapewnić zgodność wsteczną z wersją 32-bitową. Aby sprawdzić różnicę między tym a prostym 32-bitowym, musiałbyś dowiedzieć się, skąd CorFlags bierze swoją 32BITflagę w PE, nie wiem od początku mojej głowy.
Jason Larke
@JasonLarke Wylądowałem tutaj z wyszukiwarki Google, a Twój fragment kodu mi pomógł. Wielkie dzięki!
Parag Doke
@Samuel Zaktualizowano, aby sprawdzić flagę AnyCPU.
Jason Larke
że kod C # działa w procesie 64-bitowym podczas sprawdzania zestawów 32-bitowych? Na przykład błąd Module.GetPEKind msdn.microsoft.com/en-us/library/… nie działa
Kiquenet
14

W przypadku niezarządzanego pliku DLL musisz najpierw sprawdzić, czy jest to 16-bitowy plik DLL (miejmy nadzieję, że nie). Następnie sprawdź IMAGE\_FILE_HEADER.Machinepole.

Ktoś inny poświęcił trochę czasu, aby to już rozwiązać, więc powtórzę tutaj:

Aby odróżnić 32-bitowy od 64-bitowego pliku PE, należy sprawdzić pole IMAGE_FILE_HEADER.Machine. W oparciu o poniższą specyfikację Microsoft PE i COFF, wymieniłem wszystkie możliwe wartości dla tego pola: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/ pecoff_v8.doc

IMAGE_FILE_MACHINE_UNKNOWN 0x0 Zakłada się, że zawartość tego pola ma zastosowanie do dowolnego typu maszyny

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 kod bajtowy EFI

IMAGE_FILE_MACHINE_I386 0x14c Procesory Intel 386 lub nowsze i zgodne procesory

IMAGE_FILE_MACHINE_IA64 0x200 Rodzina procesorów Intel Itanium

IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R little endian

IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS z FPU

IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 z FPU

IMAGE_FILE_MACHINE_POWERPC 0x1f0 Mały endian Power PC

IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC z obsługą zmiennoprzecinkowych

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 kciuk

IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS little-endian WCE v2

Tak, możesz sprawdzić IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64 dla wersji 64-bitowej i IMAGE_FILE_MACHINE_I386 dla wersji 32-bitowej.

ShuggyCoUk
źródło
twoje drugie łącze nie działa: s
gpalex
3

Otwórz bibliotekę dll za pomocą edytora szesnastkowego, takiego jak HxD

Jeśli w dziewiątej linii znajduje się „dt”, jest to 64-bitowy.

Jeśli występuje litera „L.” w dziewiątej linii jest to 32 bity.

Philip Mc Laughlin
źródło
Nie można znaleźć „dt” i „L.” w przeglądarce HEX „Daleki menedżer”.
Dmitry,
Pokazano jako d. i L.
Zax
1

Przepisałem rozwiązanie C ++ w pierwszej odpowiedzi w skrypcie PowerShell. Skrypt może określić następujące typy plików .exe i .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  

to rozwiązanie ma pewne zalety w stosunku do corflags.exe i ładowania zestawu przez Assembly.Load w C # - nigdy nie otrzymasz BadImageFormatException ani wiadomości o nieprawidłowym nagłówku.

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

przykład użycia:

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

możesz pominąć drugi parametr, jeśli nie chcesz widzieć szczegółów

sqladmin
źródło
1

Szybki i prawdopodobnie brudny sposób na zrobienie tego jest opisany tutaj: https://superuser.com/a/889267 . Otwierasz bibliotekę DLL w edytorze i sprawdzasz pierwsze znaki po sekwencji „PE”.

ohgodnotanotherone
źródło
0

Najwyraźniej można go znaleźć w nagłówku przenośnego pliku wykonywalnego. Narzędzie corflags.exe może pokazać, czy jest przeznaczony dla x64. Mamy nadzieję, że pomoże ci to znaleźć więcej informacji na ten temat.

Steven Behnke
źródło
3
Dzięki, Steven, ale corflags.exe nie działa z natywnymi zespołami.
Ohad Horesh
1
Windows 10:>corflags libzmq.dll \n\n ... corflags : error CF008 : The specified file does not have a valid managed header
Grault