Magic
Dziedzina IMAGE_OPTIONAL_HEADER
(choć nie ma nic opcjonalnie o nagłówku w systemie Windows (pliki wykonywalne zdjęć DLL / EXE)) powie architekturę PE.
Oto przykład pobierania architektury z pliku.
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)) {
if (reader.ReadUInt16() != 23117)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
stream.Seek(0x3A, System.IO.SeekOrigin.Current);
stream.Seek(reader.ReadUInt32(), System.IO.SeekOrigin.Begin);
if (reader.ReadUInt32() != 17744)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
stream.Seek(20, System.IO.SeekOrigin.Current);
return reader.ReadUInt16();
}
}
Obecnie jedyne dwie stałe architektury to:
0x10b - PE32
0x20b - PE32+
Twoje zdrowie
AKTUALIZACJA
Minęło trochę czasu, odkąd opublikowałem tę odpowiedź, ale nadal widzę, że od czasu do czasu dostaje kilka pozytywnych głosów, więc pomyślałem, że warto to zaktualizować. Napisałem sposób na uzyskanie architektury Portable Executable
obrazu, który również sprawdza, czy został skompilowany jako AnyCPU
. Niestety odpowiedź jest w C ++, ale nie powinno być zbyt trudno przenieść się do C #, jeśli masz kilka minut na sprawdzenie struktur WinNT.h
. Jeśli ludzie są zainteresowani, napiszę port w C #, ale jeśli ludzie tego nie chcą, nie spędzę zbyt wiele czasu na stresowaniu się tym.
#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) {
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) {
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;
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;
PE_ARCHITECTURE architecture = (PE_ARCHITECTURE)pNtHd->OptionalHeader.Magic;
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);
if ((pClrHd->Flags & COMIMAGE_FLAGS_32BITREQUIRED) == 0)
architecture = PE_ARCHITECTURE_ANYCPU;
}
}
return architecture;
}
Funkcja akceptuje wskaźnik do obrazu PE w pamięci (więc możesz wybrać swoją truciznę, jak ją zdobyć; mapowanie pamięci lub wczytywanie całości do pamięci ... cokolwiek).