Search code examples
c++windowswinapiprocessreadprocessmemory

ReadProcessMemory Crashes Application When Trying to Read 32bit Integer From Another Process


I have been experimenting with various aspects of the Windows API and thought I would give process memory manipulation a try. Previously I had been trying to do this in native C++ using this method: C++ - Get value of a particular memory address

However, this method does not work and I found a response somewhere on the Cplusplus forum that told me to use ReadProcessMemory. I found that WriteProcessMemory works just fine when attempting to edit values, but ReadProcessMemory either fails (returning error code 299) or crashes the application.

Here is my code:

#include <iostream>
#include <cstdint>
#include <Windows.h>
#include <cstdio>

using namespace std;

int main()
{
    LPVOID bytes;
    DWORD pid;
    SIZE_T *num_bytes_read;
    int temp;
    SIZE_T size = sizeof(temp);
    LPCVOID address = reinterpret_cast<int*>(0x404004);
    HWND hwnd = FindWindow(NULL, "C:\\Users\\Delkarix\\Desktop\\memory_edit_test.exe");
    GetWindowThreadProcessId(hwnd, &pid);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

    BOOL worked = ReadProcessMemory(hProcess, address, bytes, size, num_bytes_read);
    cout << "ERROR: " << GetLastError() << endl;
    cout << "PROCESS: " << hProcess << endl;
    cout << "BYTES: " << bytes << endl;
    cout << "BASE ADDRESS: " << address << endl;
    cout << "FUNCTION SUCCESS: " << worked << endl;
    cout << "BYTES READ: " << *num_bytes_read << endl;
    CloseHandle(hProcess);
}

I have noticed that the application crashes when the num_bytes_read variable is a pointer (the 5th parameter of ReadProcessMemory is the num_bytes_read variable) and it throws error 299 when it is not a pointer (the 5th parameter of ReadProcessMemory is the pointer to the num_bytes_read variable).

Here is the code for the memory_edit_test.cpp:

#include <iostream>

using namespace std;

int test = 6;
int main() {
    string input;
    cout << &test << endl; // Where I got the address 0x404004
    getline(cin, input);
    cout << test << endl; // Used to check the value against the one I got from ReadProcessMemory
    getline(cin, input);
}

How can I get ReadProcessMemory to succeed? Answers to similar questions on StackOverflow either do nothing or they just make the problem worse.


Solution

  • The problem is very simple, third parameter to ReadProcessMemory is meant to point to a buffer, where the memory read will be written to. You just give it an unintialised pointer. Similar problem with the fifth parameter as well.

    Your code should look something like this

    int temp;
    SIZE_T num_bytes_read;
    BOOL worked = ReadProcessMemory(hProcess, address, &temp, sizeof temp, &num_bytes_read);
    

    Note third and fifth parameters are pointers to already existing memory. Declare a variable and use & to get its address.