C#在进程内存中搜索字节数组

问题描述 投票:2回答:1

我正在为特定的应用程序开发一个小内存扫描程序。当我选择要扫描的进程时,我要做的第一件事就是验证进程是特定应用程序的实例......为此,我必须找到一个可以在其内存中的任何位置的签名。

这是我的代码:

[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern Boolean ReadProcessMemory([In] IntPtr processHandle, [In] IntPtr processAddress, [Out] Byte[] buffer, [In] UInt32 bytesToRead, [Out] out IntPtr bytesRead); 

[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] 
internal static extern UInt32 VirtualQueryEx([In] IntPtr processHandle, [In, Optional] IntPtr processAddress, [Out] out MEMORY_BASIC_INFORMATION buffer, [In] UInt32 bufferSize); 



internal struct MEMORY_BASIC_INFORMATION 
{ 
    public static UInt32 Size = (UInt32)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)); 

    public IntPtr BaseAddress; 
    public IntPtr AllocationBase; 
    public AllocationProtect AllocationProtect; 
    public IntPtr RegionSize; 
    public StateEnum State; 
    public AllocationProtect Protect; 
    public TypeEnum lType; 
} 



public void Open() 
{ 
    Byte[] toFind = new Byte[] { 31, 55, 78, 33, 00, 00, 00, 37 }; 
    UInt32 address = 0; 

    do 
    { 
        MEMORY_BASIC_INFORMATION info = new MEMORY_BASIC_INFORMATION();

        if (NativeMethods.VirtualQueryEx(m_Process.Handle, (IntPtr)address, out info, NativeMethods.MemoryBasicInformation.Size) == 0)
            break;

        Byte[] buffer = new Byte[(UInt32)info.RegionSize]; 
        IntPtr bytesRead; 

        if (NativeMethods.ReadProcessMemory(m_Process.Handle, info.BaseAddress, buffer, (UInt32)buffer.Length, out bytesRead)) 
        { 
            if (buffer.Contains(toFind)) // Extension Method 
            {
                m_IsValid = true;
                break;
            }
        }

        if (address == (UInt32)info.BaseAddress + (UInt32)info.RegionSize) 
            break; 

        address = (UInt32)info.BaseAddress + (UInt32)info.RegionSize; 
    } 
    while (address <= 0x7fffffff); 
}

第一个问题是这个方法永远不会完成,看起来它是无休止地循环(昨天我让它运行调试目的超过一个小时而没有到达终点)。在我的循环中检查Marshal.GetLastWin32Error()我注意到有时候在调用ERROR_PARTIAL_COPY (0x0000012B)之后我得到了一个ReadProcessMemory ...这可能是原因吗?

然后我也有一些问题:

1)我应该在继续扫描循环之前调用OpenProcess吗?我不这么认为,对吧?

2)我想使我的应用程序兼容x32和x64。我应该在我的代码中更改什么以确保它能够正确地使用两个系统(address限制,address的值类型,RegionSize演员......)?

3)在扫描进程内存以找到我的目标字节数组时,我应该检查当前MEMORY_BASIC_INFORMATION的属性(AllocationProtectStateProtect和/或lType),看看我是否可以跳过当前区域的ReadProcessMemory,因为它没有必要或它无法读取?

4)我还能做些什么来优化这种方法的速度,这非常重要吗?

c# .net pinvoke readprocessmemory
1个回答
0
投票

Oooooooook我解决了它。问题是我在不使用VirtualQueryEx并检查内存区域保护的情况下尝试读取它的方式!

© www.soinside.com 2019 - 2024. All rights reserved.