ReadProcessMemory vs MiniDumpWriteDump

729 views Asked by At

I noticed that if I try to read the entirety of the process with ReadProcessMemory it takes VERY long. However, when doing a MiniDumpWriteDump, it happens in about 1 second.

Also for some reason the byte array becomes corrupt when trying to store the entire process when doing ReadProcessMemory and MiniDumpWriteDump doesn't.

Only problem is, when doing a MiniDumpWriteDump, I can't match the addresses/values in something like Cheat Engine. Like for example doing a byte array search returns a different address.

MiniDumpWriteDump(pHandle, procID, fsToDump.SafeFileHandle.DangerousGetHandle(), 0x00000002, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

ReadProcessMemory(pHandle, (UIntPtr)0, test, (UIntPtr)procs.PrivateMemorySize, IntPtr.Zero);

ReadProcessMemory Length = 597577728

Dump Length = 372053153

1

There are 1 answers

0
GuidedHacking On

if I try to read the entirety of the process with ReadProcessMemory it takes VERY long.

MiniDumpWriteDump is fast because it's a highly optimized function written my Microsoft themselves.

A proper pattern scan function that is checking page protection type and state by using VirtualQueryEx() with a limited number of wildcards won't take more than 10 seconds and in most cases will take less than 2 seconds.

This is C++ code but the logic will be the same in C#

#include <iostream>
#include <windows.h>

int main()
{
    MEMORY_BASIC_INFORMATION meminfo;
    char* addr = 0;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());

    MEMORY_BASIC_INFORMATION mbi;

    char buffer[0x1000];

    while (VirtualQueryEx(hProc, addr, &mbi, sizeof(mbi)))
    {
        if (mbi.State != MEM_COMMIT || mbi.Protect == PAGE_NOACCESS)
        {
            char* buffer = new char[mbi.RegionSize];

            ReadProcessMemory(hProc, addr, buffer, mbi.RegionSize, nullptr);
        }
        addr += mbi.RegionSize;
    }

    CloseHandle(hProc);
}

Notice we check for MEM_COMMIT, if the memory isn't commited then it's invalid. Similarly if the protection is PAGE_NOACCESS we discard that memory as well. This simple technique will yield only proper memory worth scanning, resulting in a fast scan. After you Read each section into the local buffer, you can run your pattern scan code against that. Lastly just resolve the offset from the beginning of the region to the absolute address in the target process.