Как определить, на какой платформе компилируется исполняемый файл?
Мне нужно работать с исполняемыми файлами Windows, которые сделаны для x86, x64 и IA64. Я хотел бы программно определить платформу, просмотрев сами файлы.
Мой целевой язык - PowerShell, но пример С#. Если это не так, если вы знаете логику, которая была бы велика.
Ответы
Ответ 1
(из другого Q, поскольку удален)
Тип машины: это быстрый код кода, основанный на некоторых, которые получают метку времени компоновщика. Это находится в том же заголовке, и, похоже, он работает - он возвращает I386 при компиляции -any cpu- и x64 при компиляции с ним в качестве целевой платформы.
Ввод записи блога заголовков PE (K. Stanton, MSDN), который показал мне смещение, как заметил другой ответ.
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;
}
Ответ 2
Если у вас установлена Visual Studio, вы можете использовать dumpbin.exe
. Также существует командлет Get-PEHeader
в Расширения сообщества PowerShell, который можно использовать для проверки исполняемых изображений.
Dumpbin сообщит DLL как machine (x86)
или machine (x64)
Get-PEHeader сообщит DLL как о PE32
или PE32+
Ответ 3
Вам нужна функция GetBinaryType win32. Это вернет соответствующие части исполняемого файла PE-формата.
Как правило, вы получите либо SCS_32BIT_BINARY, либо SCS_64BIT_BINARY в поле BinaryType,
Alternativaly вы можете проверить сам формат PE, чтобы посмотреть, для какой архитектуры скомпилирован исполняемый файл.
В поле IMAGE_FILE_HEADER.Machine будет установлен "IMAGE_FILE_MACHINE_IA64" для двоичных файлов IA64, IMAGE_FILE_MACHINE_I386 для 32-разрядных и IMAGE_FILE_MACHINE_AMD64 для 64-разрядных (т.е. x86_64).
Там статья журнала MSDN, чтобы помочь вам начать работу.
Приложение: Это может помочь вам немного больше. Вы читаете двоичный файл как файл: проверьте первые 2 байта, скажем "MZ", затем пропустите следующие 58 байтов и прочитайте магическое 32-битное значение в 60 байт в изображение (что равно 0x00004550 для исполняемых файлов PE). Следующие байты этот заголовок, первые 2 байта которого указывают вам, для какой машины предназначен бинарный файл (0x8664 = x86_64, 0x0200 = IA64, 0x014c = i386).
(исполнительное резюме: чтение байтов 65 и 66 файла для получения типа изображения)
Ответ 4
Assembly assembly = Assembly.LoadFile(Path.GetFullPath("ConsoleApplication1.exe"));
Module manifestModule = assembly.ManifestModule;
PortableExecutableKinds peKind;
ImageFileMachine machine;
manifestModule.GetPEKind(out peKind, out machine);
Конечная машина должна быть в машине.
Это будет работать только с сборками .NET.
Ответ 5
Я могу предложить ссылку на некоторый код С# для доступа к IMAGE_FILE_HEADER, который, как я думаю, может быть (легко) скомпилирован в командлет PowerShell, Я уверен, что вы не можете использовать этот метод в PowerShell script напрямую, поскольку ему не хватает указателей и возможностей PInvoke.
Тем не менее, вы должны иметь возможность использовать ваши обширные знания формата заголовка PE;-) просто пойти "прямо" в нужные байты и понять это. Это будет работать в PowerShell script, и вы сможете просто преобразовать этот код С# из блога Tasos в script. Я не буду повторять код здесь, так как он не мой.
Ответ 6
Unix OS имеет утилиту под названием "файл", которая идентифицирует файлы. Правила идентификации хранятся в файле описания, называемом "магия". Вы можете попробовать файл, чтобы узнать, может ли он правильно идентифицировать ваши файлы и извлечь из магического файла соответствующие правила.
Ответ 7
Вот моя собственная реализация, которая имеет еще несколько проверок и всегда возвращает результат.
// 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;
}
Как использовать:
string myfile = @"c:\windows\explorer.exe"; // the file
FilePEType pe = GetFilePE( myfile );
System.Diagnostics.WriteLine( pe.ToString() );
Для значений перечисления, используемых здесь, они были получены из pe.go. Причина, по которой это происходит, заключается в том, что для каждого двоичного значения "go" должен быть правильный флаг в сборке, чтобы он мог пропускать операционные системы ", можете ли вы запустить здесь?" проверить. Поскольку "go" - это кросс-платформа (все платформы), это хорошая база для получения этой информации. Вероятно, есть другие источники этой информации, но они, похоже, вложены в колено в google ca-ca, требуя найти 10-й дан-черный пояс в Google-fu.