开发者

Detecting the CPU architecture of specific process in C#

I writing code in C#. My code gonna run in Any CPU mode and elevated.

My goal is enumerating all processes in the machine with Process.GetProcesses(), and for each process detect its CPU archi开发者_开发百科tecture: x86, x64 or IA64.

I'm implementing code injection in C# and need to detect the architecture of the target process to decide what opcodes to inject.

How to do that?

Thanks.


Define:

    [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 will return you info about the machine you're running on. GetSystemInfo will return you info about the virtualised environment you're running within (which will be the same as GetNativeSystemInfo if there isn't one).

I.e: On 32 bit Windows, you will have wProcessorArchitecture == ProcessorArchitectureIntel always.

On 64 bit Windows, you will have wProcessorArchitecture == ProcessorArchitectureIntel for GetSystemInfo, but wProcessorArchitecture == ProcessorArchitectureAmd64 for GetNativeSystemInfo, if you are running as a 32 bit process.

They will obviously both be ProcessorArchitectureAmd64 if you're a 64 bit process on 64 bit Windows.


You have to call out to Win32 to get this information:

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

Calling IsWow64Process(process) for each process will tell you whether is it 64-bit or not. I've not come across a method to determine whether a process is x64 or IA64, just its "bitness".


You could p/invoke QueryFullProcessImageName or GetProcessImageFileName and then read the PE header of the .exe file.


Alastair is right in that you cannot just call IsWow64Process, but you also dont need to call another WinApi function directly. Here's a shorter solution.

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


You can try to P/Invoke:

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


I think y'all are on the right track, but the return value is missing a not operator. If you're on a 64-bit machine and the process is WOW64, then it's a 32-bit process (see comments above IsWow64Process). Also, the possibility of IsWow64Process returning an error is not being handled. Here's a fixed 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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜