Comment puis-je déterminer pour quelle plate-forme un exécutable est compilé?

j'ai besoin de travailler avec des exécutables Windows qui sont faits pour x86, x64 et IA64. J'aimerais programmer la plateforme en examinant les fichiers eux-mêmes.

ma langue cible est PowerShell mais un exemple de C# fera l'affaire. Si vous échouez à l'un ou l'autre de ces tests, si vous connaissez la logique nécessaire, ce serait génial.

47
demandé sur halr9000 2008-10-13 19:16:55

10 réponses

(d'un autre Q, supprimé depuis)

Type Machine: il s'agit d'un petit peu de code I basé sur certains qui obtient le timestamp linker. Ceci est dans le même en - tête, et semble fonctionner-il renvoie I386 lorsqu'il est compilé-n'importe quel cpu -, et x64 lorsqu'il est compilé avec cela comme plate-forme cible.

L'Exploration de PE-Têtes (K. Stanton,MSDN) à l'entrée de blog qui m'a montré le décalage, comme une autre réponse a été noté.

public enum MachineType {
    Native = 0, I386 = 0x014c, Itanium = 0x0200, x64 = 0x8664
}

public static MachineType GetMachineType(string fileName)
{
    const int PE_POINTER_OFFSET = 60;            
    const int MACHINE_OFFSET = 4;
    byte[] data = new byte[4096];
    using (Stream s = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
        s.Read(data, 0, 4096);
    }
    // dos header is 64 bytes, last element, long (4 bytes) is the address of the PE header
    int PE_HEADER_ADDR = BitConverter.ToInt32(data, PE_POINTER_OFFSET);
    int machineUint = BitConverter.ToUInt16(data, PE_HEADER_ADDR + MACHINE_OFFSET);
    return (MachineType)machineUint;
}
22
répondu Andrew Backer 2009-05-19 23:11:09

si vous avez Visual Studio installé vous pouvez utiliser dumpbin.exe . Il y a aussi le cmdlet Get-PEHeader dans les PowerShell Community Extensions qui peut être utilisé pour tester les images exécutables.

Dumpbin signalera DLLs comme machine (x86) ou machine (x64) 151990920"

Get-PEHeader fera rapport Dll comme PE32 ou PE32+

36
répondu Keith Hill 2015-12-22 15:01:14

vous avez besoin de la fonction win32 GetBinaryType. Ceci retournera les parties pertinentes de L'exécutable au format PE.

typiquement, vous obtiendrez soit SCS_32BIT_BINARY ou SCS_64BIT_BINARY dans le champ BinaryType,

Alternativaly vous pouvez vérifier le format PE lui-même pour voir quelle architecture l'exécutable est compilé pour.

the IMAGE_FILE_HEADER.Le champ Machine aura" IMAGE_FILE_MACHINE_IA64 " défini pour les binaires IA64, IMAGE_FILE_MACHINE_I386 pour 32 bits et IMAGE_FILE_MACHINE_AMD64 pour 64 bits (ie x86_64).

Il y a un article MSDN magazine pour vous aider à aller de l'avant.

Addendum: Ce peut vous aider un peu plus. Vous lisez le binaire comme un fichier: cochez les 2 premiers octets en disant "MZ", puis sautez les 58 octets suivants et lisez la valeur magique de 32 bits à 60 octets dans l'image (qui égale 0x00004550 pour les exécutables PE). Le les octets suivants sont cet en-tête , dont les 2 premiers octets indiquent pour quelle machine le binaire est conçu (0x8664 = x86_64, 0x0200 = IA64, 0x014c = i386).

(exécutif résumé: lire des octets 65 et 66 du fichier pour obtenir le type d'image)

11
répondu gbjbaanb 2008-10-14 21:41:41
Assembly assembly = Assembly.LoadFile(Path.GetFullPath("ConsoleApplication1.exe"));
Module manifestModule = assembly.ManifestModule;
PortableExecutableKinds peKind;
ImageFileMachine machine;
manifestModule.GetPEKind(out peKind, out machine);

La machine cible doit alors être en machine.

ça ne marchera qu'avec les assemblages .NET.

8
répondu ICR 2008-10-13 15:33:03

selon ce post , vous pouvez vérifier si une DLL ou EXE est 32 ou 64 en l'ouvrant avec Bloc-notes et à la recherche de" PE "au début, si la lettre suivante est" L "la plate-forme est 32 bits, il la lettre est" D " la plate-forme est 64bit.

j'ai essayé sur mes dlls et il semble être précis.

2
répondu mrelva 2018-03-05 12:05:55

je peux offrir un lien vers un code C# pour accéder à L'IMAGE_FILE_HEADER, qui je pense pourrait être (facilement) compilé dans un cmdlet PowerShell. Je suis raisonnablement sûr que vous ne pouvez pas utiliser cette méthode dans le script PowerShell directement, car il manque des pointeurs et des capacités PInvoke.

cependant, vous devriez être en mesure d'utiliser votre connaissance maintenant étendue du format D'en-tête PE; -) pour simplement aller "directement" aux bytes de droite et de le comprendre. Ce va travailler en script PowerShell, et vous devriez être en mesure de convertir CE C# code du blog de Tasos en script. Je ne vais pas me donner la peine de répéter le code ici puisque ce n'est pas le mien.

1
répondu Jaykul 2008-10-13 17:45:09

Unix OS ont un utilitaire appelé "file" qui identifie les fichiers. Les règles d'identification sont conservées dans un fichier de description appelé "magie". Vous pouvez essayer le fichier pour voir s'il est capable d'identifier vos fichiers correctement et de saisir les règles appropriées du fichier magique.

0
répondu Sec 2008-10-13 15:23:16

voici ma propre mise en œuvre de ce qui a plusieurs contrôles en place et renvoie toujours un résultat.

// the enum of known pe file types
public enum FilePEType : ushort
{
    IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
    IMAGE_FILE_MACHINE_AM33 = 0x1d3,
    IMAGE_FILE_MACHINE_AMD64 = 0x8664,
    IMAGE_FILE_MACHINE_ARM = 0x1c0,
    IMAGE_FILE_MACHINE_EBC = 0xebc,
    IMAGE_FILE_MACHINE_I386 = 0x14c,
    IMAGE_FILE_MACHINE_IA64 = 0x200,
    IMAGE_FILE_MACHINE_M32R = 0x9041,
    IMAGE_FILE_MACHINE_MIPS16 = 0x266,
    IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
    IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
    IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
    IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
    IMAGE_FILE_MACHINE_R4000 = 0x166,
    IMAGE_FILE_MACHINE_SH3 = 0x1a2,
    IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
    IMAGE_FILE_MACHINE_SH4 = 0x1a6,
    IMAGE_FILE_MACHINE_SH5 = 0x1a8,
    IMAGE_FILE_MACHINE_THUMB = 0x1c2,
    IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
}

// pass the path to the file and check the return
public static FilePEType GetFilePE(string path)
{
    FilePEType pe = new FilePEType();
    pe = FilePEType.IMAGE_FILE_MACHINE_UNKNOWN;
    if(File.Exists(path))
    {
        using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            byte[] data = new byte[4096];
            fs.Read(data, 0, 4096);
            ushort result = BitConverter.ToUInt16(data, BitConverter.ToInt32(data, 60) + 4);
            try
            {
                pe = (FilePEType)result;
            } catch (Exception)
            {
                pe = FilePEType.IMAGE_FILE_MACHINE_UNKNOWN;
            }
        }
    }
    return pe;
}

comment utiliser:

string myfile = @"c:\windows\explorer.exe"; // the file
FilePEType pe = GetFilePE( myfile );

System.Diagnostics.WriteLine( pe.ToString() );

pour les valeurs enum utilisées ici, elles ont été obtenues à partir de pe.allez . La raison pour laquelle cela fonctionne est que pour chaque distribution binaire de " go "doit avoir le drapeau correct dans l'assemblage pour le laisser passer les systèmes d'exploitation" pouvez-vous courir ici ?' vérifier. Depuis "go" est multi plate-forme (toutes plates-formes), c'est une bonne base pour obtenir cette information. Il existe probablement d'autres sources pour cette information, mais ils semblent être niché genou-profondément dans google ca-ca nécessitant une 10 dan ceinture noire dans Google-fu pour localiser.

0
répondu Kraang Prime 2016-08-06 17:32:06

Voici une implémentation en C.

// Determines if DLL is 32-bit or 64-bit.
#include <stdio.h>

int sGetDllType(const char *dll_name);

int main()
{
  int ret;
  const char *fname = "sample_32.dll";
  //const char *fname = "sample_64.dll";
  ret = sGetDllType(fname);
}

static int sGetDllType(const char *dll_name) {
  const int PE_POINTER_OFFSET = 60;
  const int MACHINE_TYPE_OFFSET = 4;
  FILE *fp;
  unsigned int ret = 0;
  int peoffset;
  unsigned short machine;

  fp = fopen(dll_name, "rb");
  unsigned char data[4096];
  ret = fread(data, sizeof(char), 4096, fp);
  fclose(fp);
  if (ret == 0)
    return -1;

  if ( (data[0] == 'M') && (data[1] == 'Z') ) {
    // Initial magic header is good
    peoffset = data[PE_POINTER_OFFSET + 3];
    peoffset = (peoffset << 8) + data[PE_POINTER_OFFSET + 2];
    peoffset = (peoffset << 8) + data[PE_POINTER_OFFSET + 1];
    peoffset = (peoffset << 8) + data[PE_POINTER_OFFSET];

    // Check second header
    if ((data[peoffset] == 'P') && (data[peoffset + 1] == 'E')) {
      machine = data[peoffset + MACHINE_TYPE_OFFSET];
      machine = (machine)+(data[peoffset + MACHINE_TYPE_OFFSET + 1] << 8);

      if (machine == 0x014c)
        return 32;
      if (machine == 0x8664)
        return 64;

      return -1;
    }
    return -1;
  }
  else
    return -1;
}
0
répondu Jiminion 2018-05-22 15:50:22

dumpbin.exe disponible sous bin répertoire des œuvres visuelles de Studio pour .lib et .dll

 dumpbin.exe /headers *.dll |findstr machine
 dumpbin.exe /headers *.lib |findstr machine
0
répondu Saad Saadi 2018-07-11 05:55:39