2008-10-13 7 views

Antwort

21

(von einem anderen Q, da entfernt)

Maschinentyp: Dies ist eine kurze wenig Code, den ich auf einige basiert, die den Linker Zeitstempel erhält. Dies ist in der gleichen Kopfzeile und es scheint zu funktionieren - es gibt I386 zurück, wenn es kompiliert wird - Any cpu-, und x64, wenn damit als die Zielplattform kompiliert wird.

Die Exploring PE Header (K. Stanton, MSDN) Blogeintrag, der mir den Offset zeigte, wie eine andere Antwort festgestellt.

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 OS haben ein Dienstprogramm namens "Datei", die Dateien identifiziert. Die Regeln zur Identifizierung werden in einer Beschreibungsdatei namens "magic" gespeichert. Sie könnten Datei versuchen, um zu sehen, ob es in der Lage ist, Ihre Dateien korrekt zu identifizieren und die entsprechenden Regeln aus der magischen Datei zu entnehmen.

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

Das Zielgerät sollte dann in der Maschine sein.

Das funktioniert jedoch nur mit .NET-Assemblys.

+0

Dies funktioniert gut, wenn die Ziel-Binärdatei geladen werden kann. In meinem Fall gab es eine .NET-DLL, die VCRedist benötigte und ich versuchte herauszufinden, welcher (x86 oder x64) der .NET-DLL entspricht. Aber logisch und ironisch kann ich diese .NET-DLL nicht laden, ohne dass VCRedist installiert ist und daher nicht erkennen kann, welche (mit dieser Methode) benötigt wird. – Nicolas

11

Sie benötigen die Funktion GetBinaryType win32. Dies wird die relevanten Teile des ausführbaren PE-Formats zurückgeben.

Normalerweise werden Sie entweder SCS_32BIT_BINARY oder SCS_64BIT_BINARY im binary Feld bekommen,

Alternativaly Sie das PE-Format überprüfen selbst zu sehen, welche Architektur die ausführbare Datei für kompiliert wird.

IMAGE_FILE_HEADER.Machine Das Feld für IA64-Binärdateien, IMAGE_FILE_MACHINE_I386 für 32-Bit- und IMAGE_FILE_MACHINE_AMD64 für 64-Bit (dh x86_64) haben "IMAGE_FILE_MACHINE_IA64" gesetzt wird.

Es gibt eine MSDN magazine article, die Ihnen hilft, in Gang zu kommen.

Nachtrag: This kann Ihnen ein wenig mehr helfen. Sie lesen die Binärdatei als eine Datei: überprüfen Sie die ersten 2 Bytes sagen "MZ", dann überspringen Sie die nächsten 58 Bytes und lesen Sie die magische 32-Bit-Wert bei 60 Bytes in das Bild (was gleich 0x00004550 für PE ausführbare Dateien). Die folgenden Bytes sind this header, wobei die ersten 2 Bytes Ihnen sagen, für welche Maschine die Binärdatei bestimmt ist (0x8664 = x86_64, 0x0200 = IA64, 0x014c = i386).

(Zusammenfassung: Lesen Bytes 65 und 66 der Datei den Bildtyp zu erhalten)

+0

Das ist informativer als hilfreich in meinem Fall. Meine Schuld, nicht deine. :) Ich brauche etwas, das mich näher bringt. – halr9000

+0

Entschuldigung, alter Junge, ich bin nicht mit Powershell au-fait, aber ich hoffe, dass ich dich auf den richtigen Weg gesetzt habe. Siehe meine Bearbeitung. – gbjbaanb

+0

Ich werde in dieser nächsten Woche loslegen und am Ende Ihre als "die Antwort" markieren. – halr9000

1

ich einen link to some C# code für den Zugriff auf den IMAGE_FILE_HEADER bieten kann, was ich denken konnte, (leicht) sein, in einem Powershell-Cmdlets zusammengestellt. Ich bin mir ziemlich sicher, dass Sie diese Methode nicht direkt im PowerShell-Skript verwenden können, da es Zeiger und PInvoke-Fähigkeit fehlt.

Allerdings sollten Sie in der Lage sein, Ihr mittlerweile umfangreiches Wissen über das PE-Header-Format zu nutzen ;-), gehen Sie einfach "gerade" zu den richtigen Bytes und finden Sie es heraus. Diese wird in PowerShell-Skript arbeiten, und Sie sollten this C# code from Tasos' blog in Skript konvertieren können. Ich werde den Code hier nicht wiederholen, da er nicht meiner ist.

+0

Link zu Tasos Blogpost funktioniert nicht. Dies ist einer der Gründe, warum Sie relevante Teile eines Links in Ihre Antwort aufnehmen sollten. –

+0

Tasos-Seite im Webarchiv: http://web.archive.org/web/20080113025340/http://www.anastasiosyal.com/archive/2007/04/17/3.aspx –

35

Wenn Sie Visual Studio installiert haben, können Sie dumpbin.exe verwenden. Es gibt auch das Cmdlet Get-PEHeader in PowerShell Community Extensions, das zum Testen ausführbarer Bilder verwendet werden kann.

Dumpbin berichten DLLs machine (x86) oder machine (x64)

Get-PEHeader DLLs entweder als berichten PE32 oder PE32+

+0

Ehrfürchtig. Get-PEHeader macht für Sie, was die beiden (aktuell) am besten bewerteten Antworten Ihnen lediglich Informationen geben, um sich selbst zu schreiben. PSCX FTW. – Jaykul

+0

http://StackOverflow.com/a/16181743/64257 hat auch Code für ein ähnliches (wahrscheinlich reduzierte Funktionalität) Cmdlet genau hier auf Stack Overflow. – Chris

+18

Für diejenigen (wie mich), die zu faul sind, das Handbuch zu lesen: 'dumpbin/headers | findstr machine' –

0

Hier ist meine eigene Implementierung dieser ist, die mehrere Kontrollen an Ort und Stelle hat und gibt immer ein Ergebnis .

// 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; 
} 

Wie verwenden:

string myfile = @"c:\windows\explorer.exe"; // the file 
FilePEType pe = GetFilePE(myfile); 

System.Diagnostics.WriteLine(pe.ToString()); 

Für die ENUM-Werte hier verwendet wurden, wurden sie von pe.go erhalten. Der Grund, warum dies funktioniert, ist, dass für jede binäre Verteilung von 'go' die korrekte Flagge in der Assembly verwendet werden muss, damit sie die Betriebssysteme passieren kann. "Können Sie hier laufen?" prüfen. Da "go" plattformübergreifend ist (alle Plattformen), ist es eine gute Basis, um diese Informationen zu erhalten. Es gibt wahrscheinlich andere Quellen für diese Informationen, aber sie scheinen in Google ca-ca geschachtelt zu sein, was einen 10. dan black belt in Google-fu erfordert.

0

Nach dieser post, können Sie überprüfen, ob eine DLL oder EXE 32 oder 64, indem sie es mit Notizbuch und der Suche nach „PE“ am Anfang geöffnet wird, wenn der nächste Buchstabe „L“ ist die Plattform 32 -Bit, es ist der Buchstabe "D" die Plattform ist 64bit.

Ich habe es auf meine DLLs versucht und es scheint genau zu sein.