Wie finde ich heraus, ob eine native DLL-Datei als x64 oder x86 kompiliert ist?

133

Ich möchte feststellen, ob eine native Assembly von einer verwalteten Codeanwendung ( C # ) als x64 oder x86 erfüllt wird .

Ich denke, es muss sich irgendwo im PE-Header befinden, da der OS-Loader diese Informationen kennen muss, aber ich konnte sie nicht finden. Natürlich bevorzuge ich es in verwaltetem Code, aber wenn es nötig ist, kann ich natives C ++ verwenden.

Ohad Horesh
quelle
Um klar zu sein, ist die fragliche DLL auch eine .Net-Assembly? Sie sagen native DLL im Titel des Beitrags, aber native Assembly in der Beschreibung ... wenn Sie diesen Beitrag noch aktiv von 09 betrachten :)
Vikas Gupta
1
Vielleicht möchten Sie auch Folgendes überprüfen: Überprüfen Sie, ob die nicht verwaltete DLL-32-Bit-oder-64-Bit ist .
Matt

Antworten:

143

Sie können auch DUMPBIN verwenden . Verwenden Sie das Flag /headersoder /allund den ersten aufgelisteten Dateikopf.

dumpbin /headers cv210.dll

64-Bit

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

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

'finden' kann das Leben etwas erleichtern:

dumpbin /headers cv210.dll |find "machine"
        8664 machine (x64)
Mark McDonald
quelle
4
Etwas benutzerfreundlicher;)
Ant
4
DUMPBIN funktioniert nicht für .NET EXEs. Ich habe eine 64-Bit-.NET-EXE-Datei, von der DUMPBIN sagt, dass sie 32-Bit ist ("14C-Maschine (x86)"), aber Corflags sagt, dass es sich um eine beliebige CPU handelt ("PE: PE32, 32BIT: 0"). Abhängigkeits-Walker diagnostiziert es auch falsch.
Pierre
2
Es erforderte mspdb100.dll:(
Dmitry
1
@Altaveron Ich hatte das gleiche Problem, habe es jedoch behoben, indem ich die DLL-Datei mspdb100.dllin den Ordner kopiert habe, in dem sie dumpbin.exesich befindet. DUMPBINkann danach laufen. Für mich ist die EXE bei <Visual Studio Install folder>\VC\binund die DLL ist bei <Visual Studio Install folder>\Common7\IDE.
ADTC
DUMPBIN ist an der Visual Studio-Eingabeaufforderung für Benutzer mit installiertem Visual Studio verfügbar
Alan Macdonald
55

Mit CorFlags ist dies auf einfache Weise möglich . Öffnen Sie die Visual Studio-Eingabeaufforderung und geben Sie "corflags [Ihre Assembly]" ein. Sie werden so etwas bekommen:

c: \ Programme (x86) \ Microsoft Visual Studio 9.0 \ VC> corflags "C: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ System.Data.dll"

Microsoft (R) .NET Framework CorFlags-Konvertierungstool. Version 3.5.21022.8 Copyright (c) Microsoft Corporation. Alle Rechte vorbehalten.

Version: v2.0.50727 CLR-Header: 2.5 PE: PE32 CorFlags: 24 ILONLY: 0 32BIT: 0 Signiert: 1

Sie betrachten speziell PE und 32BIT.

  • Beliebige CPU :

    PE: PE32
    32BIT: 0

  • x86 :

    PE: PE32
    32BIT: 1

  • x64:

    PE: PE32 +
    32BIT: 0

BLogan
quelle
18
@BLogan du solltest dir meinen Kommentar zu Steven Behnke oben ansehen. Ich kenne das Dienstprogramm corflags, aber es funktioniert nicht bei nativen Assemblys.
Ohad Horesh
7
Welche Corflags-Ausgaben wurden in letzteren Versionen (Windows SDK 8 oder höher) geändert? Anstelle von 32BIT hat es jetzt 32BITREQUIRED und 32BITPREFERRED. Siehe Beschreibung in CorHdr.h unter C: \ Programme (x86) \ Windows Kits \ 8.0 \ Include \ um \ CorHdr.h. Nach allem, was ich sagen kann, ersetzt 32BITREQUIRED 32BIT. Siehe auch Antwort auf diese Frage .
Wes
37

Dieser Trick funktioniert und erfordert nur Notepad.

Öffnen Sie die DLL-Datei mit einem Texteditor (wie Notepad) und suchen Sie das erste Vorkommen der Zeichenfolge PE. Das folgende Zeichen definiert, ob die DLL 32 oder 64 Bit umfasst.

32 Bit:

PE  L

64 Bit:

PE  d
Zanon
quelle
24

Das MagicFeld von IMAGE_OPTIONAL_HEADER(obwohl der Header in ausführbaren Windows-Images (DLL / EXE-Dateien) nicht optional ist) gibt Auskunft über die Architektur des PE.

Hier ist ein Beispiel für das Abrufen der Architektur aus einer Datei.

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

Die einzigen zwei Architekturkonstanten im Moment sind:

0x10b - PE32
0x20b - PE32+

Prost

UPDATE Es ist schon eine Weile her, dass ich diese Antwort gepostet habe, aber ich sehe immer noch, dass es ab und zu ein paar Upvotes gibt, also dachte ich, dass es sich lohnt, sie zu aktualisieren. Ich habe einen Weg geschrieben, um die Architektur eines Portable ExecutableBildes zu erhalten, der auch prüft, ob es als kompiliert wurde AnyCPU. Leider ist die Antwort in C ++, aber es sollte nicht zu schwierig sein, auf C # zu portieren, wenn Sie ein paar Minuten Zeit haben, um die Strukturen nachzuschlagen WinNT.h. Wenn die Leute interessiert sind, schreibe ich einen Port in C #, aber wenn die Leute es nicht wirklich wollen, werde ich nicht viel Zeit damit verbringen, darüber nachzudenken.

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

Die Funktion akzeptiert einen Zeiger auf ein In-Memory-PE-Bild (so können Sie Ihr Gift auswählen, wie Sie es erhalten möchten; Speicherzuordnung oder Einlesen des Ganzen in den Speicher ... was auch immer).

Jason Larke
quelle
Sehr interessant, aber wenn ich eine Anwendung mit einer beliebigen CPU kompiliert habe, ist das Ergebnis 0x10B. Dies ist falsch, da meine Anwendung auf einem x64-System ausgeführt wird. Gibt es noch eine andere Flagge zu überprüfen?
Samuel
3
AnyCPU bedeutet genau das: AnyCPU, daher wird es im PE-Header als 0x10B aufgeführt, um die Abwärtskompatibilität mit 32-Bit zu gewährleisten. Um den Unterschied zwischen diesem und 32-Bit-Straight zu überprüfen, müssen Sie herausfinden, woher CorFlags seine 32BITFlagge in der PE bezieht. Ich weiß es nicht genau.
Jason Larke
@ JasonLarke Ich bin hier von einer Google-Suche gelandet und Ihr Code-Snippet hat mir geholfen. Danke vielmals!
Parag Doke
@Samuel Aktualisiert, um das AnyCPU-Flag zu überprüfen.
Jason Larke
dass C # -Code in einem 64-Bit-Prozess funktioniert, wenn 32-Bit-Assemblys überprüft werden? Zum Beispiel schlägt Module.GetPEKind msdn.microsoft.com/en-us/library/… fehl
Kiquenet
14

Bei einer nicht verwalteten DLL-Datei müssen Sie zunächst prüfen, ob es sich um eine 16-Bit-DLL-Datei handelt (hoffentlich nicht). Dann überprüfen Sie das IMAGE\_FILE_HEADER.MachineFeld.

Jemand anderes hat sich die Zeit genommen, dies bereits zu klären, deshalb werde ich hier nur wiederholen:

Um zwischen einer 32-Bit- und einer 64-Bit-PE-Datei zu unterscheiden, sollten Sie das Feld IMAGE_FILE_HEADER.Machine überprüfen. Basierend auf der folgenden Microsoft PE- und COFF-Spezifikation habe ich alle möglichen Werte für dieses Feld aufgelistet: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/ pecoff_v8.doc

IMAGE_FILE_MACHINE_UNKNOWN 0x0 Es wird davon ausgegangen, dass der Inhalt dieses Felds für jeden Maschinentyp gilt

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

IMAGE_FILE_MACHINE_I386 0x14c Intel 386 oder neuere Prozessoren und kompatible Prozessoren

IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium-Prozessorfamilie

IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R Little Endian

IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS mit FPU

IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 mit FPU

IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC Little Endian

IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC mit Gleitkomma-Unterstützung

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

Ja, Sie können IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64 für 64 Bit und IMAGE_FILE_MACHINE_I386 für 32 Bit überprüfen.

ShuggyCoUk
quelle
Ihr zweiter Link ist tot: s
gpalex
3

Öffnen Sie die DLL mit einem Hex-Editor wie HxD

Wenn es in der 9. Zeile ein "dt" gibt, ist es 64bit.

Wenn es ein "L." in der 9. Zeile ist es 32bit.

Philip Mc Laughlin
quelle
Kann "dt" und "L." nicht finden. auf dem HEX-Viewer "Far Manager".
Dmitry
Dargestellt als d. und L.
Zax
1

Ich habe die C ++ - Lösung in der ersten Antwort im Powershell-Skript umgeschrieben. Das Skript kann diese Arten von EXE- und DLL-Dateien bestimmen:

#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  

Diese Lösung hat einige Vorteile gegenüber corflags.exe und dem Laden von Assemblys über Assembly.Load in C # - Sie erhalten niemals eine BadImageFormatException oder eine Meldung über einen ungültigen Header.

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

Anwendungsbeispiel:

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

Sie können den zweiten Parameter weglassen, wenn Sie keine Details sehen müssen

sqladmin
quelle
1

Eine schnelle und wahrscheinlich schmutzige Vorgehensweise wird hier beschrieben: https://superuser.com/a/889267 . Sie öffnen die DLL in einem Editor und überprüfen die ersten Zeichen nach der "PE" -Sequenz.

ohgodnotanotherone
quelle
0

Anscheinend finden Sie es in der Kopfzeile der tragbaren ausführbaren Datei. Das Dienstprogramm corflags.exe kann Ihnen anzeigen, ob es auf x64 abzielt oder nicht. Hoffentlich hilft Ihnen dies dabei, weitere Informationen darüber zu finden.

Steven Behnke
quelle
3
Danke Steven, aber corflags.exe funktioniert nicht mit nativen Assemblys.
Ohad Horesh
1
Windows 10:>corflags libzmq.dll \n\n ... corflags : error CF008 : The specified file does not have a valid managed header
Grault