2008-10-13 49 views
46

我需要使用適用於x86,x64和IA64的Windows可執行文件。我想通過檢查文件本身來以編程方式確定平臺。如何確定可執行文件編譯的平臺?

我的目標語言是PowerShell,但是一個C#示例可以。如果你知道所要求的邏輯很好,那麼這兩者中的任何一個都不行。

回答

21

(從另一個Q,因爲刪除)

機器類型:這是我根據一些獲取鏈接時間戳的代碼快速點點。這是在同一個頭,它似乎工作 - 編譯時,它會返回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; 
} 
0

Unix操作系統有一個名爲「文件」的實用程序來識別文件。識別規則保存在一個名爲「magic」的描述文件中。您可以嘗試查看文件是否能夠正確識別您的文件,並從魔術文件中獲取適當的規則。

8
Assembly assembly = Assembly.LoadFile(Path.GetFullPath("ConsoleApplication1.exe")); 
Module manifestModule = assembly.ManifestModule; 
PortableExecutableKinds peKind; 
ImageFileMachine machine; 
manifestModule.GetPEKind(out peKind, out machine); 

目標機器應該在機器中。

雖然這隻能用於.NET程序集。

+0

如果可以加載目標二進制文件,這可以很好地工作。在我的情況下,有一個.NET DLL需要VCRedist,我試圖找出哪一個(x86或x64),對應於.NET DLL。但是,邏輯上和諷刺的是,如果沒有安裝VCRedist,我無法加載這個.NET DLL,因此無法檢測到它需要哪個(使用此方法)。 – Nicolas 2015-12-07 13:33:03

11

您需要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 magazine article來幫助你開始。

附錄:This可能會幫助你多一點。您將二進制讀取爲一個文件:檢查前兩個字節,如「MZ」,然後跳過下一個58個字節,並讀取60個字節的魔術32位值(等於PE可執行文件的0x00004550)。以下字節爲this header,其中的前2個字節告訴您該二進制文件設計爲哪臺計算機(0x8664 = x86_64,0x0200 = IA64,0x014c = i386)。

(內容提要:讀取的字節65和文件66來獲取圖像類型)

+0

對我而言,這比我的幫助更有價值。我的錯,不是你的。 :)我需要讓我更接近的東西。 – halr9000 2008-10-13 16:06:03

+0

對不起老朋友,我不喜歡PowerShell,但我希望我能讓你走上正確的道路。看我的編輯。 – gbjbaanb 2008-10-14 21:31:36

+0

我將在下週出發,並可能最終將您標爲「答案」。 – halr9000 2008-10-19 00:10:59

1

我可以訪問IMAGE_FILE_HEADER,我想這可能是提供一個link to some C# code(容易)編譯成PowerShell命令。我相當肯定你不能直接在PowerShell腳本中使用該方法,因爲它缺少指針和PInvoke功能。

但是,你應該能夠通過PE頭格式;-)現在廣泛的知識用你只是去「直」,以正確的字節,看着辦吧。這工作在PowerShell腳本,你應該能夠將this C# code from Tasos' blog轉換爲腳本。我不會在這裏重複代碼,因爲它不是我的。

35

如果您安裝了Visual Studio,則可以使用dumpbin.exePowerShell Community Extensions中還有Get-PEHeader cmdlet,可用於測試可執行映像。

DUMPBIN將報告的DLL作爲machine (x86)machine (x64)

GET-PEHeader將報告的DLL作爲要麼PE32PE32+

0

這是我自己實現的這裏面有幾個檢查到位,並始終返回結果。

// 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'的每個二進制分佈,在程序集中必須有正確的標記才能讓它通過操作系統'你可以在這裏運行嗎?'檢查。由於'去'是跨平臺(所有平臺),因此它是獲取此信息的好基礎。這些信息可能還有其他來源,但它們似乎在google ca-ca中嵌套在一起,需要Google-fu中的第10個黑帶才能找到。

0

根據這一post,您可以檢查是否DLL或EXE爲32或64的開頭與記事本打開它,並尋找「PE」,如果下一個字母爲「L」的平臺是32它的字母是「D」,平臺是64位。

我在我的dll上試過了,它似乎是準確的。

相關問題