You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WriteProcessMemory调用返回错误299的问题排查求助

Troubleshooting WriteProcessMemory Error 299 in Your Game Hacking Test

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 WriteProcessMemory parameter: Changed (LPCVOID)val to &val so 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_OPERATION instead of PROCESS_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 bytesWritten to 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:22:56