Comment savoir si un fichier DLL natif est compilé au format x64 ou x86?

133

Je veux déterminer si un assembly natif est conforme en tant que x64 ou x86 à partir d'une application de code managé ( C # ).

Je pense que cela doit être quelque part dans l'en-tête PE car le chargeur du système d'exploitation doit connaître ces informations, mais je ne les ai pas trouvées. Bien sûr, je préfère le faire en code managé, mais si nécessaire, je peux utiliser le C ++ natif.

Ohad Horesh
la source
Pour être clair, la dll en question est également un assembly .Net? Vous dites DLL native dans le titre du message, mais assemblage natif dans la description ... si vous regardez toujours activement ce message à partir de 09 :)
Vikas Gupta
1
Vous pouvez également consulter celui-ci: check-if-unmanaged-dll-is-32-bit-or-64-bit .
Matt

Réponses:

143

Vous pouvez également utiliser DUMPBIN . Utilisez l' indicateur /headersou /allet son premier en-tête de fichier répertorié.

dumpbin /headers cv210.dll

64 bits

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 bits

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

`` trouver '' peut rendre la vie un peu plus facile:

dumpbin /headers cv210.dll |find "machine"
        8664 machine (x64)
Mark McDonald
la source
4
Un peu plus convivial;)
Ant
4
DUMPBIN ne fonctionne pas pour les EXE .NET. J'ai un EXE .NET 64 bits qui, selon DUMPBIN, est 32 bits ("machine 14C (x86)"), mais corflags dit que c'est Any CPU ("PE: PE32, 32BIT: 0"). Dependency Walker le diagnostique également de manière erronée.
Pierre
2
Il a requis mspdb100.dll:(
Dmitry
1
@Altaveron J'ai eu le même problème, mais je l'ai résolu en copiant le fichier DLL mspdb100.dlldans le dossier où dumpbin.exese trouve. DUMPBINpeut courir après cela. Pour moi, le EXE est à <Visual Studio Install folder>\VC\binet la DLL est à <Visual Studio Install folder>\Common7\IDE.
ADTC
DUMPBIN est disponible à partir de l'invite de commande Visual Studio pour ceux avec Visual Studio installé
Alan Macdonald
55

Il existe un moyen simple de le faire avec CorFlags . Ouvrez l'invite de commandes Visual Studio et tapez "corflags [votre assembly]". Vous obtiendrez quelque chose comme ça:

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

Outil de conversion CorFlags Microsoft (R) .NET Framework. Version 3.5.21022.8 Copyright (c) Microsoft Corporation. Tous les droits sont réservés.

Version: v2.0.50727 En-tête CLR: 2.5 PE: PE32 CorFlags: 24 ILONLY: 0 32BIT: 0 Signé: 1

Vous regardez spécifiquement PE et 32BIT.

  • Tout processeur :

    PE: PE32 32BIT
    : 0

  • x86 :

    PE: PE32 32BIT
    : 1

  • x64:

    PE: PE32 + 32BIT
    : 0

BLogan
la source
18
@BLogan, vous devriez regarder mon commentaire à Steven Behnke ci-dessus. Je connais l'utilitaire corflags mais il ne fonctionne pas sur les assemblys natifs.
Ohad Horesh
7
Ce que Corflags produit a changé dans les dernières versions (Windows SDK 8 ou supérieur). Maintenant, au lieu de 32BIT, il a 32BITREQUIRED et 32BITPREFERRED. Voir la description dans CorHdr.h situé dans C: \ Program Files (x86) \ Windows Kits \ 8.0 \ Include \ um \ CorHdr.h. D'après ce que je peux dire, 32BITREQUIRED remplace 32BIT. Voir également la réponse à cette question .
Wes du
37

Cette astuce fonctionne et ne nécessite que le bloc-notes.

Ouvrez le fichier dll à l'aide d'un éditeur de texte (comme le Bloc-notes) et recherchez la première occurrence de la chaîne PE. Le caractère suivant définit si la dll est 32 ou 64 bits.

32 bits:

PE  L

64 bits:

PE  d
Zanon
la source
25

Le Magicchamp du IMAGE_OPTIONAL_HEADER(bien qu'il n'y ait rien de facultatif à propos de l'en-tête dans les images exécutables Windows (fichiers DLL / EXE)) vous indiquera l'architecture du PE.

Voici un exemple de capture de l'architecture à partir d'un fichier.

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

Les deux seules constantes d'architecture pour le moment sont:

0x10b - PE32
0x20b - PE32+

À votre santé

MISE À JOUR Cela fait un moment que j'ai publié cette réponse, mais je vois toujours qu'elle reçoit quelques votes positifs de temps en temps, alors j'ai pensé que cela valait la peine d'être mis à jour. J'ai écrit un moyen d'obtenir l'architecture d'une Portable Executableimage, qui vérifie également si elle a été compilée comme AnyCPU. Malheureusement, la réponse est en C ++, mais il ne devrait pas être trop difficile de porter en C # si vous avez quelques minutes pour rechercher les structures WinNT.h. Si les gens sont intéressés, j'écrirai un portage en C #, mais à moins que les gens ne le veuillent réellement, je ne passerai pas beaucoup de temps à le stresser.

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

La fonction accepte un pointeur vers une image PE en mémoire (vous pouvez donc choisir votre poison sur la façon de l'obtenir; mappage de mémoire ou lecture du tout en mémoire ... peu importe).

Jason Larke
la source
Très intéressant mais quand j'ai une application compilée avec Any CPU, le résultat est 0x10B. C'est faux car mon application est exécutée dans un système x64. Y a-t-il un autre drapeau à vérifier?
Samuel
3
AnyCPU signifie juste que: AnyCPU, donc il est répertorié comme 0x10B dans l'en-tête PE pour une compatibilité ascendante avec 32 bits. Pour vérifier la différence entre cela et le 32 bits simple, vous devez savoir d'où CorFlags tire son 32BITdrapeau dans le PE, je ne sais pas par-dessus ma tête.
Jason Larke
@JasonLarke J'ai atterri ici à partir d'une recherche Google et votre extrait de code m'a aidé. Merci beaucoup!
Parag Doke
@Samuel Mise à jour pour vérifier l'indicateur AnyCPU.
Jason Larke
que le code C # fonctionne dans un processus 64 bits lors de la vérification des assemblys 32 bits? Par exemple, Module.GetPEKind msdn.microsoft.com/en-us/library/… échoue
Kiquenet
14

Pour un fichier DLL non géré, vous devez d'abord vérifier s'il s'agit d'un fichier DLL 16 bits (espérons que non). Vérifiez ensuite le IMAGE\_FILE_HEADER.Machinechamp.

Quelqu'un d'autre a déjà pris le temps de résoudre ce problème, alors je vais simplement répéter ici:

Pour faire la distinction entre un fichier PE 32 bits et 64 bits, vous devez vérifier le champ IMAGE_FILE_HEADER.Machine. Basé sur la spécification Microsoft PE et COFF ci-dessous, j'ai répertorié toutes les valeurs possibles pour ce champ: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/ pecoff_v8.doc

IMAGE_FILE_MACHINE_UNKNOWN 0x0 Le contenu de ce champ est supposé être applicable à tout type de machine

IMAGE_FILE_MACHINE_AM33 0x1d3 Matsushita AM33

IMAGE_FILE_MACHINE_AMD64 0x8664 x64

IMAGE_FILE_MACHINE_ARM 0x1c0 ARM petit boutien

IMAGE_FILE_MACHINE_EBC 0xebc Code d'octet EFI

IMAGE_FILE_MACHINE_I386 0x14c Processeurs Intel 386 ou version ultérieure et processeurs compatibles

IMAGE_FILE_MACHINE_IA64 0x200 Famille de processeurs Intel Itanium

IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R petit boutiste

IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS avec FPU

IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 avec FPU

IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC petit boutiste

IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC avec prise en charge de la virgule flottante

IMAGE_FILE_MACHINE_R4000 0x166 MIPS petit boutiste

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 Pouce

IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS petit-boutiste WCE v2

Oui, vous pouvez vérifier IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64 pour 64 bits et IMAGE_FILE_MACHINE_I386 pour 32 bits.

ShuggyCoUk
la source
votre deuxième lien est mort: s
gpalex
3

Ouvrez la dll avec un éditeur hexadécimal, comme HxD

S'il y a un "dt" sur la 9ème ligne, c'est 64 bits.

S'il y a un "L." sur la 9ème ligne, c'est 32 bits.

Philip Mc Laughlin
la source
Impossible de trouver "dt" et "L." sur le visualiseur HEX "Far Manager".
Dmitry
Montré comme d. and L.
Zax
1

J'ai réécrit la solution c ++ en première réponse dans le script PowerShell. Script peut déterminer ces types de fichiers .exe et .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  

cette solution présente certains avantages par rapport à corflags.exe et au chargement de l'assembly via Assembly.Load en C # - vous n'obtiendrez jamais BadImageFormatException ou un message sur un en-tête non valide.

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

exemple d'utilisation:

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

vous pouvez omettre le deuxième paramètre si vous n'avez pas besoin de voir les détails

sqladmin
la source
1

Une façon rapide et probablement sale de le faire est décrite ici: https://superuser.com/a/889267 . Vous ouvrez la DLL dans un éditeur et vérifiez les premiers caractères après la séquence "PE".

ohgodnotanotherone
la source
0

Apparemment, vous pouvez le trouver dans l'en-tête de l'exécutable portable. L'utilitaire corflags.exe est capable de vous montrer s'il cible ou non x64. J'espère que cela vous aidera à trouver plus d'informations à ce sujet.

Steven Behnke
la source
3
Merci Steven mais corflags.exe ne fonctionne pas avec les assemblys natifs.
Ohad Horesh le
1
Windows 10:>corflags libzmq.dll \n\n ... corflags : error CF008 : The specified file does not have a valid managed header
Grault