C# Search Byte Array inside Process Memory

2

I'm developing a little memory scanner for a specific application. When I select a process to scan, the first thing I want to do is to verify that the process is an instance that specific application... and to do this I must find a signature that can be anywhere inside its memory.

Here is my code:

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

The first problem that this method is never reaching completion and it looks like it's endlessly looping (yesterday I let it running for debug purposes for more than one hour without reaching the end). Checking for Marshal.GetLastWin32Error() inside my loop I noticed that sometimes I get an ERROR_PARTIAL_COPY (0x0000012B) after calling ReadProcessMemory... is it the possible cause?

Then I also have some questions:

1) Should I call OpenProcess before proceeding with the scan loop? I don't think so, right?

2) I would like to make my application both x32 and x64 compatible. What should I change inside my code to be sure it will properly work with both systems (address limit, value type of address, RegionSize cast, ...)?

3) While scanning the process memory in order to find my target byte array, should I check the current MEMORY_BASIC_INFORMATION's properties (AllocationProtect, State, Protect and/or lType) to see if I can skip ReadProcessMemory for the current region because it's not necessary or it can't be read?

4) Is there anything else I can do to optimize the speed of this methos, which is very important?

c#
.net
pinvoke
readprocessmemory
asked on Stack Overflow Apr 24, 2013 by Tommaso Belluzzo • edited Sep 3, 2018 by Uwe Keim

1 Answer

0

Oooooooook I solved it. The problem was the way I was trying to read it without using VirtualQueryEx and checking for the memory region protection!

answered on Stack Overflow May 3, 2013 by Tommaso Belluzzo

User contributions licensed under CC BY-SA 3.0