Le champ Magic
du IMAGE_OPTIONAL_HEADER
(bien que le header des images exécutables Windows (fichiers DLL/EXE) ne soit en réalité pas optionnel) vous donnera l'architecture du PE.
Voici un exemple pour récupérer 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)) {
// Vérifier la signature MZ pour s'assurer qu'il s'agit d'une image exécutable Portable valide
if (reader.ReadUInt16() != 23117)
throw new BadImageFormatException("Pas une image exécutable Portable valide", filepath);
// rechercher, puis lire, e_lfanew puis avancer le flux jusqu'à cet endroit (début de l'en-tête NT)
stream.Seek(0x3A, System.IO.SeekOrigin.Current);
stream.Seek(reader.ReadUInt32(), System.IO.SeekOrigin.Begin);
// Assurer que l'en-tête NT est valide en vérifiant la signature "PE\0\0"
if (reader.ReadUInt32() != 17744)
throw new BadImageFormatException("Pas une image exécutable Portable valide", filepath);
// passer l'en-tête de fichier, puis lire le numéro magique de l'en-tête optionnel
stream.Seek(20, System.IO.SeekOrigin.Current);
return reader.ReadUInt16();
}
}
Les seules constantes d'architecture actuelles sont :
0x10b - PE32
0x20b - PE32+
Santé
MISE À JOUR Cela fait un moment que j'ai posté cette réponse, mais je vois qu'elle reçoit encore quelques votes de temps en temps, donc j'ai pensé qu'elle valait la peine d'être mise à jour. J'ai écrit un moyen d'obtenir l'architecture d'une image Portable Executable
, qui vérifie également si elle a été compilée en AnyCPU
. Malheureusement, la réponse est en C++, mais il ne devrait pas être trop difficile de la porter en C# si vous avez quelques minutes pour rechercher les structures dans WinNT.h
. Si les gens sont intéressés, j'écrirai une version en C#, mais à moins que les gens ne le veuillent vraiment, je ne passerai pas beaucoup de temps à m'en préoccuper.
#include
#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) {
// Rechercher quelle section contient cette RVA pour traduire l'adresse VA en un décalage de fichier
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) {
// Analyser et valider l'en-tête DOS
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;
// Analyser et valider l'en-tête NT
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;
// Première vérification naive basée sur le numéro 'Magic' dans l'en-tête optionnel.
PE_ARCHITECTURE architecture = (PE_ARCHITECTURE)pNtHd->OptionalHeader.Magic;
// Si l'architecture est x86, il y a encore une possibilité que l'image soit '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);
// Vérifier si l'en-tête CLR contient le drapeau 32BITONLY, sinon l'image est en réalité 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 (donc vous pouvez choisir votre méthode pour y accéder ; mapping en mémoire ou lecture de l'ensemble en mémoire...peu importe).
0 votes
Pour être clair, la dll en question est également une assembly .Net? Vous mentionnez une DLL native dans le titre du post, mais une assembly native dans la description... si vous regardez toujours activement ce post de 09 :)
1 votes
Vous voudrez peut-être aussi vérifier celui-ci: check-if-unmanaged-dll-is-32-bit-or-64-bit.
0 votes
Aussi lié: Comment puis-je déterminer pour quelle plateforme un exécutable est compilé?