首页 > 解决方案 > ReadProcessMemory() Returning 0 ERROR_PARTIAL_COPY

问题描述

#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>

using namespace std;

DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
   MODULEENTRY32 lpModuleEntry = {0};
   HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );

   if(!hSnapShot)
      return NULL;
   lpModuleEntry.dwSize = sizeof(lpModuleEntry);
   BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
   while(bModule)
   {
      if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
      {
         CloseHandle( hSnapShot );
         return (DWORDLONG)lpModuleEntry.modBaseAddr;
      }
      bModule = Module32Next( hSnapShot, &lpModuleEntry );
   }
   CloseHandle( hSnapShot );
   return NULL;
}


int main() {
    DWORD pID;
    DWORDLONG off1, off2;
    DWORDLONG baseAddress;
    char moduleName[] = _T("AoE2DE_s.exe");
    HWND hGameWindow;
    HANDLE pHandle;

    //Get Handles
    hGameWindow = FindWindow(NULL, "Age of Empires II: Definitive Edition");
    cout << "Game Window: " << hGameWindow << std::endl;
    GetWindowThreadProcessId(hGameWindow, &pID);
    cout << "Process ID: " << pID << std::endl;
    pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);

    cout << "Process Handle: " << std::hex << pHandle << std::endl;

    //Get Client Base Addy
    DWORDLONG clientBase = GetModuleBase(moduleName, pID);
    cout << "Client Base: " << clientBase << std::endl;
    ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
    DWORD lastError = GetLastError();
    cout << "Error: " << lastError << std::endl;
    cout << "Base Address: " << std::hex << baseAddress << std::endl;
    ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x18), &off1, sizeof(DWORDLONG), NULL);
    cout << "After Offset 1: " << std::hex << off1 << std::endl;
    ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x9230), &off2, sizeof(DWORDLONG), NULL);
    cout << "After Final Offset: " << off2 << std::endl;
    cin.get();
}

The error occurs on this line: ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);

Application output for debugging purposes:

Game Window: 0x1307c2
Process ID: 11988
Process Handle: 0xec
Client Base: cc640000
Error: 12b
Base Address: 0
After Offset 1: 401519
After Final Offset: 8

Not sure how it is failing here, I'm somewhat new to this. Everything else goes through perfectly without error's but fails on the first ReadProcessMemory() if someone can help bring the solution for this to light I would be grateful.

标签: c++winapimemoryprocess

解决方案


ReadProcessMemory 的定义如下:

BOOL ReadProcessMemory(
  HANDLE  hProcess,
  LPCVOID lpBaseAddress,
  LPVOID  lpBuffer,
  SIZE_T  nSize,
  SIZE_T  *lpNumberOfBytesRead
);

如果它返回零,则表示有错误,只有在这种情况下GetLastError才会返回一个有意义的错误号。

所以正确的用法是:

SIZE_T readBytes;
if (!ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), &readBytes)) {
  DWORD lastError = GetLastError();
  cout << "ReadProcessMemory failed: Error: " << lastError << " read " << readBytes << std::endl;
}
else
{
  cout << "ReadProcessMemory succeeded"; << std::endl;
  cout << "Base Address: " << std::hex << baseAddress << std::endl;
}

推荐阅读