我怎样才能确定一个可执行文件编译的平台?
我需要使用适用于x86,x64和IA64的Windows可执行文件。 我想以编程方式通过检查文件本身来找出平台。
我的目标语言是PowerShell,但是C#示例将会执行。 如果你知道所需要的逻辑将是伟大的,那么这两者中的任何一个都不行。
(从另一个Q,因为被删除)
机器types:这是基于一些获取链接器时间戳的代码的一小部分。 这是在同一个头,它似乎工作 – 编译时,它返回I386 -any CPU和X64编译时,作为目标平台。
作为另一个回应指出,探索PE头(K.斯坦顿,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; }
如果您安装了Visual Studio,则可以使用dumpbin.exe
。 还有PowerShell社区扩展中的Get-PEHeader
cmdlet可用于testing可执行映像。
Dumpbin会将DLL报告为machine (x86)
或machine (x64)
Get-PEHeader将报告DLL作为PE32
或PE32+
您需要GetBinaryType win32函数。 这将返回PE格式可执行文件的相关部分。
通常,您将在BinaryType字段中获得SCS_32BIT_BINARY或SCS_64BIT_BINARY,
Alternativaly你可以检查PE格式本身来查看可执行文件编译的体系结构。
IMAGE_FILE_HEADER.MACHINE字段将为IA64二进制文件设置“IMAGE_FILE_MACHINE_IA64”,32位为IMAGE_FILE_MACHINE_I386,64位(即x86_64)为IMAGE_FILE_MACHINE_AMD64。
有一个MSDN杂志的文章,以帮助你走了。
附录: 这可能会帮助你多一点。 您读取二进制文件:检查前2个字节说“MZ”,然后跳过接下来的58个字节,并读取60个字节的魔术32位值到图像(这对于PE可执行文件等于0x00004550)。 下面的字节是这个头文件 ,头两个字节告诉你二进制文件是为哪个机器devise的(0x8664 = x86_64,0x0200 = IA64,0x014c = i386)。
(执行摘要:读取文件的字节65和66以获取图像types)
Assembly assembly = Assembly.LoadFile(Path.GetFullPath("ConsoleApplication1.exe")); Module manifestModule = assembly.ManifestModule; PortableExecutableKinds peKind; ImageFileMachine machine; manifestModule.GetPEKind(out peKind, out machine);
目标机器应该在机器中。
这只会在.NET程序集中起作用。
我可以提供一些用于访问IMAGE_FILE_HEADER的C#代码的链接 ,我认为这可以(很容易)编译到PowerShell cmdlet中。 我相当确定你不能直接在PowerShell脚本中使用这个方法,因为它缺less指针和PInvokefunction。
但是,你应该能够使用你现在广泛的PE头格式的知识;-)只是“直”到正确的字节,并找出它。 这将在PowerShell脚本中起作用,您应该能够将Tasos博客中的这个C#代码转换为脚本。 我不会在这里重复代码,因为它不是我的。
Unix操作系统有一个名为“文件”的工具来识别文件。 识别规则保存在一个名为“magic”的描述文件中。 你可以尝试文件,看看它是否能够正确识别你的文件,并从魔术文件中抓取适当的规则。
这是我自己的实现这个有更多的检查,并始终返回一个结果。
// 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获得的。 之所以这样做,是因为对于每个“去”的二进制分布,在程序集中都必须有正确的标记,让它通过操作系统“你能在这里运行吗? 检查。 由于'走'是跨平台(所有平台),所以获取这些信息是一个很好的基础。 这个信息可能还有其他的来源,但是它们似乎在google ca-ca中被嵌套在一起,需要Google-fu中的第10个黑带。