views:

642

answers:

2

I'm having some problems implementing an algorithm to read a foreign process' memory. Here is the main code:

            System.Diagnostics.Process.EnterDebugMode();
            IntPtr retValue = WinApi.OpenProcess((int)WinApi.OpenProcess_Access.VMRead | (int)WinApi.OpenProcess_Access.QueryInformation, 0, (uint)_proc.Id);
            _procHandle = retValue;

            WinApi.MEMORY_BASIC_INFORMATION[] mbia = getMemoryBasicInformation().Where(p => p.State == 0x1000).ToArray();

            foreach (WinApi.MEMORY_BASIC_INFORMATION mbi in mbia) {
                byte[] buffer = Read((IntPtr)mbi.BaseAddress, mbi.RegionSize);

                foreach (IntPtr addr in ByteSearcher.FindInBuffer(buffer, toFind, (IntPtr)0, mbi.RegionSize, increment)) {
                    yield return addr;
                }
            }

Read() ... method

        if (!WinApi.ReadProcessMemory(_procHandle, address, buffer, size, out numberBytesRead)) {
            throw new MemoryReaderException(
                string.Format(
                "There was an error with ReadProcessMemory()\nGetLastError() = {0}",
                WinApi.GetLastError()
                ));
        }

Although generally it seems to work correctly, the problem is that for some memory values ReadProcessMemory is returning false, and GetLastError is returning 299. From what I've googled, it seems to happen on vista because some params of OpenProcess were updated. Anyone knows what this is about? And what values should I try? Notice that as they changed, I wouldn't want to know if it's VM_READ or so, I want to know exactly what the values are.

EDIT: maybe it has something to do with not calling VirtualProtect()/VirtualProtectEx()? as seen on this SO url: http://stackoverflow.com/questions/1112339/writeprocessmemory-readprocessmemory-fail

Edit2: That was it! ^^ That is the solution, calling to VirtualProtectEx() first and after ReadProcessMemory()!

+1  A: 
C:\Debuggers>kd -z C:\Windows\notepad.exe
0:000> !error 0n299
Error code: (Win32) 0x12b (299) - Only part of a ReadProcessMemory 
    or WriteProcessMemory request was completed.

This means you tried to read a block that was partially unmapped addresses (i.e. if the app itself did this, it'd AV)

Paul Betts
That'd be strange, as as you can see in the code, i am only going after memory blocks given by MEMORY_BASIC_INFORMATION structs. Or am I doing something wrong?
devoured elysium
Is the process suspended? Or are you reading from a live process?
Paul Betts
I'm running it on a running process. May that be the reason?
devoured elysium
Of course - as you're collecting the MEMORY_BASIC_INFORMATION (i.e. the PTEs), the process is allocating and deallocating memory.
Paul Betts
+1  A: 

You store the handle to the newly opened process in a local variable (retValue), but you don't pass it to your getMemoryBasicInformation function, so I can only assume that it actually fetches information about the current process. I suspect you're really using your own process's address ranges as though they belong to the other process. Many of the address ranges will probably be the same between processes, so that error wouldn't be immediately apparent.

Rob Kennedy
No. I am accessing correctly data from another process.
devoured elysium
Keep in mind that I just put together this parts of the code but actually it is more complex. I have tested this and it is reading data from another process.
devoured elysium
I see. My crystal ball is in the shop for repairs. In the meantime, I can only comment on code I've been shown.
Rob Kennedy