WriteProcessMemory调用返回错误299的问题排查求助
Let's break down exactly what's going wrong with your memory modifier program, and fix it step by step.
Core Issues Causing Error 299
Error 299 (ERROR_PARTIAL_COPY) pops up here for two critical reasons:
1. Invalid Buffer Address in WriteProcessMemory
Look at this line in your code:
writeResult = WriteProcessMemory(hProcess, (LPVOID)0x00DAFC58, (LPCVOID)val, sizeof(val), NULL);
The third parameter (LPCVOID)val is the problem. You're casting the integer value 2000 directly to a pointer, which means the function tries to read data from memory address 0x7D0 (hex for 2000)—a completely invalid space. WriteProcessMemory expects a pointer to the data you want to write, not the data itself.
2. Hardcoded Memory Address (ASLR Conflict)
You're using a hardcoded address 0x00DAFC58, but Windows uses Address Space Layout Randomization (ASLR) which randomizes process memory layouts every launch. That address will only work for one specific run of your game—restart the game, and the address changes entirely.
Fixed Memory Modifier Code
Here's a revised version of your program with fixes for both issues, plus better error handling:
#include <iostream> #include <Windows.h> #include <cstdint> using namespace std; int main() { HWND handle = FindWindow(NULL, L"Simple game"); if (handle == NULL) { cerr << "Failed to find game window. Error code: " << GetLastError() << endl; return 1; } cout << "Found game window handle: " << handle << endl; DWORD processId; GetWindowThreadProcessId(handle, &processId); cout << "Game process ID: " << processId << endl; // Request only the permissions we need (PROCESS_ALL_ACCESS is overkill) HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId); if (!hProcess) { cerr << "Failed to open game process. Error code: " << GetLastError() << endl; return 1; } // Ask user for the dynamic address from the game's output uintptr_t scoreAddress; cout << "Paste the score address from the game window: "; cin >> hex >> scoreAddress; int val = 2000; SIZE_T bytesWritten; BOOL writeSuccess = WriteProcessMemory( hProcess, (LPVOID)scoreAddress, &val, // Pass pointer to our value, not the value itself sizeof(val), &bytesWritten ); if (!writeSuccess) { cerr << "Write failed. Error code: " << GetLastError() << endl; } else { cout << "Success! Wrote " << bytesWritten << " bytes to memory." << endl; } // Clean up: close the process handle to avoid resource leaks CloseHandle(hProcess); return 0; }
Key Improvements Explained
- Fixed
WriteProcessMemoryparameter: Changed(LPCVOID)valto&valso the function reads the value from your program's valid memory space. - Removed hardcoded address: Added user input to get the current score address from the game's output, which works around ASLR.
- Restricted process permissions: Used
PROCESS_VM_WRITE | PROCESS_VM_OPERATIONinstead ofPROCESS_ALL_ACCESS—minimal permissions avoid unnecessary access denials. - Added resource cleanup: Called
CloseHandle(hProcess)to release the process handle when done, preventing memory leaks. - Tracked bytes written: Added
bytesWrittento verify exactly how much data was written, which helps with debugging.
Bonus: Avoid Manual Address Entry (Advanced)
To skip typing the address every time, use a base address + offset approach. Since your game's score is a local variable right now (on the stack), its offset changes every run. Fix this by making score a global variable in your game:
#include <iostream> #include <Windows.h> #include <cstdint> using namespace std; int score = 100; // Global variable (lives in the data section, fixed offset from module base) int main() { uintptr_t moduleBase = (uintptr_t)GetModuleHandle(NULL); uintptr_t scoreOffset = (uintptr_t)&score - moduleBase; SetConsoleTitle(L"Simple game"); cout << "Score address: " << &score << endl; cout << "Module base address: " << hex << moduleBase << endl; cout << "Score offset from base: 0x" << hex << scoreOffset << endl; while (true) { cout << score << " | Address: " << &score << endl; score = max(score - 1, 0); Sleep(1000); } }
Now, your modifier program can calculate the score address by getting the game's module base and adding the fixed offset. This way, you don't need to input the address manually every time.
内容的提问来源于stack exchange,提问作者agamendon

