¿Cómo encontrar si un archivo DLL nativo se compila como x64 o x86?

133

Quiero determinar si un ensamblado nativo se cumple como x64 o x86 desde una aplicación de código administrado ( C # ).

Creo que debe estar en algún lugar del encabezado PE ya que el cargador del sistema operativo necesita conocer esta información, pero no pude encontrarla. Por supuesto, prefiero hacerlo en código administrado, pero si es necesario, puedo usar C ++ nativo.

Ohad Horesh
fuente
Para ser claros, ¿el dll en cuestión es también un ensamblado .Net? Dices DLL nativo en el título de la publicación, pero ensamblaje nativo en la descripción ... si todavía estás buscando activamente esta publicación de 09 :)
Vikas Gupta
1
También es posible que desee ver este: check-if-unmanaged-dll-is-32-bit-or-64-bit .
Matt

Respuestas:

143

También puedes usar DUMPBIN . Use el indicador /headerso /ally es el primer encabezado de archivo de la lista.

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

'find' puede hacer la vida un poco más fácil:

dumpbin /headers cv210.dll |find "machine"
        8664 machine (x64)
Mark McDonald
fuente
44
Un poco más fácil de usar;)
Ant
44
DUMPBIN no funciona para .NET EXEs. Tengo un .NET EXE de 64 bits que DUMPBIN dice que es de 32 bits ("máquina 14C (x86)"), pero corflags dice que es Cualquier CPU ("PE: PE32, 32BIT: 0"). Dependency Walker también lo diagnostica erróneamente.
Pierre
2
Se requiere mspdb100.dll:(
Dmitry
1
@Altaveron Tuve el mismo problema, pero lo resolví copiando el archivo DLL mspdb100.dllen la carpeta donde dumpbin.exese encuentra. DUMPBINpuede correr después de eso. Para mí, el EXE está en <Visual Studio Install folder>\VC\biny la DLL está en <Visual Studio Install folder>\Common7\IDE.
ADTC
DUMPBIN está disponible desde el símbolo del sistema de Visual Studio para aquellos con Visual Studio instalado
Alan Macdonald
55

Hay una manera fácil de hacer esto con CorFlags . Abra el símbolo del sistema de Visual Studio y escriba "corflags [su ensamblaje]". Obtendrás algo como esto:

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

Herramienta de conversión CorFlags de Microsoft (R) .NET Framework. Versión 3.5.21022.8 Copyright (c) Microsoft Corporation. Todos los derechos reservados.

Versión: v2.0.50727 CLR Encabezado: 2.5 PE: PE32 CorFlags: 24 ILONLY: 0 32BIT: 0 Firmado: 1

Estás viendo PE y 32BIT específicamente.

  • Cualquier CPU :

    PE: PE32
    32BIT: 0

  • x86 :

    PE: PE32
    32BIT: 1

  • x64:

    PE: PE32 +
    32BIT: 0

BLogan
fuente
18
@BLogan deberías mirar mi comentario a Steven Behnke arriba. Soy consciente de la utilidad corflags pero no funciona en ensamblajes nativos.
Ohad Horesh
77
Lo que las salidas de Corflags cambiaron en las últimas versiones (Windows SDK 8 o superior). Ahora en lugar de 32BIT tiene 32BITREQUIRED y 32BITPREFERRED. Consulte la descripción en CorHdr.h ubicado en C: \ Archivos de programa (x86) \ Windows Kits \ 8.0 \ Include \ um \ CorHdr.h. Por lo que puedo decir, 32BITREQUIRED reemplaza a 32BIT. También vea la respuesta a esta pregunta .
Wes
37

Este truco funciona y solo requiere el Bloc de notas.

Abra el archivo dll usando un editor de texto (como el Bloc de notas) y encuentre la primera aparición de la cadena PE . El siguiente carácter define si el dll es de 32 o 64 bits.

32 bits:

PE  L

64 bits:

PE  d
Zanon
fuente
25

El Magiccampo de IMAGE_OPTIONAL_HEADER(aunque no hay nada opcional sobre el encabezado en las imágenes ejecutables de Windows (archivos DLL / EXE)) le indicará la arquitectura del PE.

Aquí hay un ejemplo de cómo tomar la arquitectura de un archivo.

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

Las únicas dos constantes de arquitectura en este momento son:

0x10b - PE32
0x20b - PE32+

Salud

ACTUALIZACIÓN Ha pasado un tiempo desde que publiqué esta respuesta, pero aún veo que recibe algunos votos positivos de vez en cuando, así que pensé que valía la pena actualizarla. Escribí una forma de obtener la arquitectura de una Portable Executableimagen, que también verifica si se compiló como AnyCPU. Desafortunadamente, la respuesta está en C ++, pero no debería ser demasiado difícil de transferir a C # si tiene unos minutos para buscar las estructuras WinNT.h. Si la gente está interesada, escribiré un puerto en C #, pero a menos que la gente realmente lo quiera, no pasaré mucho tiempo estresándolo.

#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 función acepta un puntero a una imagen PE en memoria (para que pueda elegir su veneno sobre cómo obtenerla; mapeo de memoria o leer todo en la memoria ... lo que sea).

Jason Larke
fuente
Muy interesante, pero cuando tengo una aplicación compilada con Any CPU, el resultado es 0x10B. Esto está mal porque mi aplicación se ejecuta en un sistema x64. ¿Hay alguna otra bandera para verificar?
Samuel
3
AnyCPU significa exactamente eso: AnyCPU, por lo que aparece como 0x10B en el encabezado PE para compatibilidad con versiones anteriores de 32 bits. Para verificar la diferencia entre eso y 32 bits, necesitaría averiguar de dónde saca CorFlags su 32BITbandera en el PE, no lo sé.
Jason Larke
@JasonLarke Llegué aquí desde una búsqueda en Google y su fragmento de código me ayudó. ¡Muchas gracias!
Parag Doke
@Samuel Actualizado para verificar la bandera de AnyCPU.
Jason Larke
que el código C # funciona en un proceso de 64 bits al verificar ensambles de 32 bits? Por ejemplo, Module.GetPEKind msdn.microsoft.com/en-us/library/… falla
Kiquenet
14

Para un archivo DLL no administrado, primero debe verificar si es un archivo DLL de 16 bits (con suerte no). Luego verifique elIMAGE\_FILE_HEADER.Machine campo.

Alguien más se tomó el tiempo para resolver esto, así que solo repetiré aquí:

Para distinguir entre un archivo PE de 32 bits y 64 bits, debe verificar el campo IMAGE_FILE_HEADER.Machine. Según las especificaciones de Microsoft PE y COFF a continuación, he enumerado todos los valores posibles para este campo: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/ pecoff_v8.doc

IMAGE_FILE_MACHINE_UNKNOWN 0x0 Se supone que el contenido de este campo es aplicable a cualquier tipo de máquina

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 Código de bytes EFI

IMAGE_FILE_MACHINE_I386 0x14c Intel 386 o procesadores posteriores y procesadores compatibles

IMAGE_FILE_MACHINE_IA64 0x200 Familia de procesadores Intel Itanium

IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R little endian

IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16

IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS con FPU

IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 con FPU

IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC little endian

IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC con soporte de coma flotante

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

Sí, puede consultar IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64 para 64 bits y IMAGE_FILE_MACHINE_I386 para 32 bits.

ShuggyCoUk
fuente
su segundo enlace está muerto: s
gpalex
3

Abra el dll con un editor hexadecimal, como HxD

Si hay un "dt" en la novena línea, es de 64 bits.

Si hay una "L" en la novena línea es de 32 bits.

Philip Mc Laughlin
fuente
No puedo encontrar "dt" y "L." en el visor HEX "Far Manager".
Dmitry
Mostrado como d. y L.
Zax
1

Reescribí la solución de C ++ en la primera respuesta en el script de PowerShell. El script puede determinar este tipo de archivos .exe y .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  

esta solución tiene algunas ventajas sobre corflags.exe y la carga del ensamblaje a través de Assembly.Load en C #: nunca obtendrá BadImageFormatException o un mensaje sobre un encabezado no válido.

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

ejemplo de uso:

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

puede omitir el segundo parámetro si no necesita ver detalles

sqladmin
fuente
1

Aquí se describe una forma rápida y probablemente sucia de hacerlo: https://superuser.com/a/889267 . Abre la DLL en un editor y verifica los primeros caracteres después de la secuencia "PE".

oh dios no otra
fuente
0

Aparentemente puedes encontrarlo en el encabezado del ejecutable portátil. La utilidad corflags.exe puede mostrarle si se dirige o no a x64. Esperemos que esto te ayude a encontrar más información al respecto.

Steven Behnke
fuente
3
Gracias Steven, pero corflags.exe no funciona con ensamblajes nativos.
Ohad Horesh
1
Windows 10:>corflags libzmq.dll \n\n ... corflags : error CF008 : The specified file does not have a valid managed header
Grault