55 votes

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

J'ai besoin de travailler avec des exécutables Windows qui sont conçus pour x86, x64 et IA64. J'aimerais pouvoir déterminer la plate-forme de manière programmatique en examinant les fichiers eux-mêmes.

Mon langage cible est PowerShell, mais un exemple en C# fera l'affaire. A défaut, si vous connaissez la logique requise, ce serait formidable.

1 votes

41voto

Keith Hill Points 73162

Si Visual Studio est installé, vous pouvez utiliser dumpbin.exe . Il y a aussi le Get-PEHeader dans la cmdlet Extensions de la communauté PowerShell qui peut être utilisé pour tester les images exécutables.

Dumpbin signale les DLL comme étant machine (x86) o machine (x64)

Get-PEHeader signalera les DLL comme étant soit PE32 o PE32+

0 votes

Génial. Get-PEHeader fait pour vous ce que les deux réponses qui sont (actuellement) les mieux notées ne font que vous donner des informations à écrire vous-même. PSCX FTW.

0 votes

stackoverflow.com/a/16181743/64257 Le code d'une cmdlet similaire (aux fonctionnalités probablement réduites) se trouve également ici, sur Stack Overflow.

25 votes

Pour ceux (comme moi) qui sont trop paresseux pour lire le manuel : dumpbin /headers <executable> | findstr machine

29voto

Andrew Backer Points 3009

(d'un autre Q, supprimé depuis)

Type de machine : Il s'agit d'un petit bout de code rapide que j'ai basé sur un autre qui récupère l'horodatage du linker. C'est dans le même en-tête, et cela semble fonctionner - il retourne I386 quand il est compilé - n'importe quel processeur -, et x64 quand il est compilé avec cette plate-forme comme cible.

L'article de blog Exploring PE Headers (K. Stanton, MSDN) qui m'a montré le décalage, comme l'a indiqué une autre réponse.

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

11voto

gbjbaanb Points 31045

Vous avez besoin de la fonction GetBinaryType win32. Elle renvoie les parties pertinentes de l'exécutable au format PE.

En général, vous obtiendrez SCS_32BIT_BINARY ou SCS_64BIT_BINARY dans le champ BinaryType,

Vous pouvez également vérifier le format PE lui-même pour voir pour quelle architecture l'exécutable a été compilé.

Le champ IMAGE_FILE_HEADER.Machine aura pour valeur "IMAGE_FILE_MACHINE_IA64" pour les binaires IA64, IMAGE_FILE_MACHINE_I386 pour les binaires 32 bits et IMAGE_FILE_MACHINE_AMD64 pour les binaires 64 bits (c'est-à-dire x86_64).

Il y a un Article du magazine MSDN pour vous aider à démarrer.

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

(résumé : lisez les octets 65 et 66 du fichier pour connaître le type d'image)

0 votes

Dans mon cas, c'est plus instructif qu'utile. C'est ma faute, pas la vôtre :) J'ai besoin de quelque chose qui me rapproche.

0 votes

Désolé, mon vieux, je ne suis pas au fait de powershell, mais j'espère que je vous ai mis sur la bonne voie.

0 votes

J'essaierai la semaine prochaine et je finirai peut-être par marquer la vôtre comme étant "la réponse".

8voto

ICR Points 6960
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 devrait alors se trouver dans la machine.

Cela ne fonctionnera cependant qu'avec les assemblages .NET.

0 votes

Cela fonctionne bien si le binaire cible peut être chargé. Dans mon cas, il y avait une dll .NET qui avait besoin de VCRedist et j'ai essayé de déterminer lequel (x86 ou x64) correspondait à la dll .NET. Mais, logiquement et ironiquement, je ne peux pas charger cette dll .NET sans que VCRedist soit installé et je suis donc incapable de détecter celui dont elle a besoin (avec cette méthode).

1voto

Jaykul Points 6484

Je peux offrir un lien vers du code C# pour accéder à l'IMAGE_FILE_HEADER, qui, je pense, pourrait être (facilement) compilée dans une cmdlet PowerShell. Je suis à peu près certain que vous ne pouvez pas utiliser cette méthode dans le script PowerShell directement, car il n'y a pas de pointeurs ni de capacité PInvoke.

Cependant, vous devriez être en mesure d'utiliser vos connaissances désormais approfondies du format de l'en-tête PE ;-) pour aller "directement" aux bons octets et trouver la solution. Ce qui suit volonté fonctionnent en PowerShell script, et vous devriez être en mesure de convertir simplement ce code C# provenant du blog de Tasos à script. Je ne prendrai pas la peine de répéter le code ici puisqu'il n'est pas le mien.

0 votes

Le lien vers l'article du blog de Tasos ne fonctionne pas. C'est l'une des raisons pour lesquelles vous devez inclure les parties pertinentes d'un lien dans votre réponse.

0 votes

La page de Tasos dans les archives Web : web.archive.org/web/20080113025340/http://www.anastasiosyal.com/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X