title: Why does my call to ReadProcessMemory() fail?
body: <p>First off, I know this looks like a duplicate but I looked through the other questions and could not find a solution so please hear me out.</p>
  
  <p>I have a function to convert relative virtual addresses to dynamic memory addresses aka read multi level pointers (shown below). I call the function with a valid handle to the remote process that has all access rights, a pointer to the processes base address(4194304 or 0x400000), the rva (29128148 or 0x1BC75D4), and the offsets ({ 20, 48, 12 }, { 0x14, 0x30, 0xC }). The line that adds the base address to the rva returns 33322452 or 0x1FC75D4 which is correct (verified through cheat engine).  The first iteration of the loop calls RPM() with the aforementioned address and the call to BitConverter.ToInt32() returns -134118400 or 0xF8018400 which is also correct.  The new value of dynamicMemoryAddress is set by adding that address and the first offset (0x14) which yeilds an IntPtr with the value of -134118380 or 0xF8018414.</p>
  
  <p>However, when RPM() is called in the second iteration with the new value of dynamicMemoryAddress (0xF8018414) the function returns failure status.  A call to GetLastError() returns 998 or ERROR_NOACCESS (Invalid access to memory location.).  In Cheat Engine I browse to 0xF8018414 and it has the correct value and the pages Protect values is PAGE_READ_WRITE so I cannot understand why the first call succeeds but the second fails even though I seem to have sufficient access rights.</p>
  
  <p>For debugging purposes I had inserted a call to VirtualQueryEx() immediatly before the call to RPM() the first iteration it succeeds and the MemoryBasicInformation struct is correctly populated, on the second iteration the struct is completely empty.</p>
  
  <p>I have been stuck on this issue for 2 days now and am at my wits end, any help is greatly appreciated.  I am running on x64 windows 7 but all the concerned processes are x86 if that is relevant.</p>
  
  <pre><code>private static IntPtr ConvertRVAToDMA(RemoteProcess rProcess, IntPtr baseAddress, IntPtr relativeVirtualAddress, Int32[] offsets)
          {
              Process.EnterDebugMode();
              byte[] buffer = new byte[Marshal.SizeOf(new IntPtr())];
              int tmpNewBaseAddress;
              IntPtr bytesRead = new IntPtr();
  
              IntPtr dynamicMemoryAddress = new IntPtr(baseAddress.ToInt32() + relativeVirtualAddress.ToInt32());
  
              try
              {
                  for (int i = 0; i &lt; (offsets.Length); i++)
                  {
                      if (!WinApis.ReadProcessMemory(rProcess.Handle, dynamicMemoryAddress, buffer, Marshal.SizeOf(new IntPtr()), out bytesRead))
                      {
                          dynamicMemoryAddress = IntPtr.Zero;
                          break;
                      }
  
                      tmpNewBaseAddress = BitConverter.ToInt32(buffer, 0);
                      if (tmpNewBaseAddress == 0)
                      {
                          dynamicMemoryAddress = IntPtr.Zero;
                          break;
                      }
  
                      dynamicMemoryAddress = IntPtr.Add((IntPtr)tmpNewBaseAddress, offsets[i]);
                  }
              }
              catch (Exception ex)
              {
                  dynamicMemoryAddress = IntPtr.Zero;
              }
              Process.LeaveDebugMode();
              return dynamicMemoryAddress;
          }
  </code></pre>