2011-01-08 6 views
3

Ich schreibe Code in C#. Mein Code läuft in Any CPU Modus und erhöht.Erkennung der CPU-Architektur eines bestimmten Prozesses in C#

Mein Ziel ist Aufzählen alle Prozesse in der Maschine mit Process.GetProcesses(), und für jeden Prozess erkennt seine CPU-Architektur: x86, x64 oder IA64.

Ich implementiere Code-Injection in C# und muss die Architektur des Zielprozesses erkennen, um zu entscheiden, welche Opcodes injiziert werden sollen.

Wie geht das?

Danke.

+2

Wenn Sie Code-Injektion implementieren, rufen Sie wahrscheinlich eine Menge von Win32-APIs? Könnte ich vorschlagen, dass die Verwendung von C++/CLI für das wird viel einfacher sein ... Sie enden damit.NET-Klassen genau so, als ob Sie sie in C# geschrieben hätten, aber Sie müssen sich nicht mit der Übersetzung aller Strukturen herumschlagen, da der C++ - Compiler das für Sie direkt aus den Win32-Header-Dateien erledigt. –

+0

+1 zu Ben. Vergessen Sie auch nicht, dass 1.0/1.1/2.0 CLR nicht 2 Laufzeiten im Prozess hosten kann. Sie müssen also herausfinden, ob der Prozess verwalteten Code ausführt (oder ob später andere Versionen von verwaltetem Code ausgeführt werden) und passenden Code injizieren (Sie sollten mindestens 2.0 Version des Codes zusätzlich zu 4.0 haben) –

+0

@Alexei: Kann nicht der gleiche Prozess .NET 4 zur gleichen Zeit wie 1.0/1.1/2.0 haben? Wenn Sie also .NET 4-Code injizieren, ist es egal, ob bereits eine CLR-Version geladen wurde. –

Antwort

0

Sie können versuchen, zu P/Invoke:

BOOL WINAPI IsWow64Process( __in HANDLE hProcess, __out PBOOL Wow64Process); 
1

Sie müssen Win32 rufen diese Informationen zu erhalten:

[System.Runtime.InteropServices.DllImport("kernel32.dll")] 
public static extern bool IsWow64Process(System.IntPtr hProcess, out bool lpSystemInfo); 

public bool IsWow64Process(System.Diagnostics.Process process) 
{ 
    bool retVal = false; 
    IsWow64Process(process.Handle, out retVal); 
    return retVal; 
} 

Aufruf IsWow64Process(process) für jeden Prozess wird Ihnen sagen, ob es 64 -Bit oder nicht. Ich bin nicht auf eine Methode gestoßen, um festzustellen, ob ein Prozess x64 oder IA64 ist, nur seine "Bitness".

+0

IA64-Prozessoren können x86_64-Code nicht ausführen, oder? Daher würde die lokale Maschinenarchitektur diese unterscheiden. Oder suchen Sie die dem Prozess entsprechende ausführbare Datei und überprüfen Sie den PE-Header. –

+0

Das ist nicht richtig. IsWow64Process teilt Ihnen mit, ob Sie in einem 32-Bit-Prozess unter einem 64-Bit-Betriebssystem arbeiten. Dadurch wird bei 32-Bit-Windows für 32-Bit-Anwendungen und bei 64-Bit-Windows für 64-Bit-Anwendungen false zurückgegeben. Sehen Sie meine Antwort unten für wie man es richtig macht. –

1

Sie könnten p/invoke QueryFullProcessImageName oder GetProcessImageFileName und dann lesen Sie den PE-Header der EXE-Datei.

+1

Ich mag diesen Ansatz mehr. Sehen Sie hier, wie Sie die Architektur von PE-Header erhalten http://StackOverflow.com/questions/197951/How-Can-Ide-Determine-for-which-platform-an-executable-is-compiled –

+0

Obwohl [ImageTheader '] (http://msdn.microsoft.com/en-us/library/ms680212.aspx) ist der zukunftssichere Weg, den Header zu finden. –

+0

Ich mag das nicht wirklich. Sie müssen jede zukünftige Erweiterung des PE-Formats unterstützen. Zum Beispiel müssen Sie auch .net-Header verstehen. Und wenn Sie ein Ziel wie "Any CPU" treffen, wird es noch komplizierter. – CodesInChaos

2

definieren:

[DllImport("kernel32.dll")] 
    internal static extern void GetNativeSystemInfo(ref SystemInfo lpSystemInfo); 

    [DllImport("kernel32.dll")] 
    internal static extern void GetSystemInfo(ref SystemInfo lpSystemInfo); 

    [StructLayout(LayoutKind.Sequential)] 
    internal struct SystemInfo 
    { 
     public ushort wProcessorArchitecture; 
     public ushort wReserved; 
     public uint dwPageSize; 
     public IntPtr lpMinimumApplicationAddress; 
     public IntPtr lpMaximumApplicationAddress; 
     public UIntPtr dwActiveProcessorMask; 
     public uint dwNumberOfProcessors; 
     public uint dwProcessorType; 
     public uint dwAllocationGranularity; 
     public ushort wProcessorLevel; 
     public ushort wProcessorRevision; 
    } 

    internal const ushort ProcessorArchitectureIntel = 0; 
    internal const ushort ProcessorArchitectureIa64 = 6; 
    internal const ushort ProcessorArchitectureAmd64 = 9; 
    internal const ushort ProcessorArchitectureUnknown = 0xFFFF; 

GetNativeSystemInfo kehren Sie Informationen über die Maschine laufen lassen Sie. GetSystemInfo gibt Ihnen Informationen über die virtualisierte Umgebung zurück, in der Sie sich befinden (die gleiche wie GetNativeSystemInfo, wenn es keine gibt).

Ie: Auf 32-Bit-Windows haben Sie immer wProcessorArchitecture == ProcessorArchitectureIntel.

Auf 64-Bit-Windows werden Sie wProcessorArchitecture == ProcessorArchitectureIntel für GetSystemInfo, aber wProcessorArchitecture == ProcessorArchitectureAmd64 für GetNativeSystemInfo haben, wenn Sie sich als 32-Bit-Prozess ausgeführt werden.

Sie werden offensichtlich beide ProcessorArchitectureAmd64 sein, wenn Sie ein 64-Bit-Prozess auf 64-Bit-Windows sind.

1

Alastair hat Recht damit, dass Sie nicht nur IsWow64Process aufrufen können, sondern auch nicht direkt eine andere WinApi Funktion aufrufen müssen. Hier ist eine kürzere Lösung.

/// <summary> 
    /// TRUE if the process is running under WOW64. That is if it is a 32 bit process running on 64 bit Windows. 
    /// If the process is running under 32-bit Windows, the value is set to FALSE. 
    /// If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE. 
    /// </summary> 
    [DllImport("kernel32.dll")] 
    static extern bool IsWow64Process(System.IntPtr aProcessHandle, out bool lpSystemInfo); 

    /// <summary> 
    /// Indicates if the process is 32 or 64 bit. 
    /// </summary> 
    /// <param name="aProcessHandle">process to query</param> 
    /// <returns>true: process is 64 bit; false: process is 32 bit</returns> 
    public static bool Is64BitProcess(System.IntPtr aProcessHandle) 
    { 
     bool lIs64BitProcess = false; 
     if (System.Environment.Is64BitOperatingSystem) { 
      IsWow64Process(aProcessHandle, out lIs64BitProcess); 
     } 
     return lIs64BitProcess; 
    } 
0

Ich denke, Sie sind auf der richtigen Spur, aber der Rückgabewert fehlt ein Nicht-Operator. Wenn Sie sich auf einer 64-Bit-Maschine befinden und der Prozess WOW64 ist, handelt es sich um einen 32-Bit-Prozess (siehe Kommentare über IsWow64Process). Außerdem wird die Möglichkeit, dass IsWow64Process einen Fehler zurückgibt, nicht behandelt. Hier ist eine feste Version:

/// <summary> 
/// TRUE if the process is running under WOW64. That is if it is a 32 bit process running on 64 bit Windows. 
/// If the process is running under 32-bit Windows, the value is set to FALSE. 
/// If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE. 
/// </summary> 
[DllImport("kernel32.dll", SetLastError=true)] 
static extern bool IsWow64Process(System.IntPtr aProcessHandle, out bool isWow64Process); 

/// <summary> 
/// Indicates if the process is 32 or 64 bit. 
/// </summary> 
/// <param name="aProcessHandle">process to query</param> 
/// <returns>true: process is 64 bit; false: process is 32 bit</returns> 
public static bool Is64BitProcess(System.IntPtr aProcessHandle) 
{ 
    if (!System.Environment.Is64BitOperatingSystem) 
     return false; 

    bool isWow64Process; 
    if (!IsWow64Process(aProcessHandle, out isWow64Process)) 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 

    return !isWow64Process; 
}