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

64位C++内存地址偏移计算问题求助

64位内存地址偏移计算错误排查

问题概述

计算带偏移的64位内存地址时出现错误:32位场景下可正常实现,但64位场景结果不符合预期。例如,基地址0x000002586F08CE30加上偏移0x88后,实际得到0x2586F08CEB8,但预期结果应为0x25825C4C880。

错误代码分析

用户的错误代码片段如下:

void aVoid()
{
    DWORD64* add = (DWORD64*)0x000002586F08CE30;
    cout << add << endl;

    DWORD64* off = (DWORD64*)0x88;
    cout << off << endl;

    DWORD64* BaseTimeAddress = (DWORD64*)((char*)add + (DWORD64)off);
    cout << BaseTimeAddress << endl;    // Gets 000002586F08CEB8
}

核心错误点:

  • 混淆指针地址与指针指向的值:代码直接将基地址指针add作为数值与偏移相加,但实际需要先读取add指向的内存中存储的64位地址值,再加上偏移。
  • 偏移类型冗余:将偏移0x88定义为DWORD64*指针类型完全多余,直接用数值类型DWORD64存储即可。

修正方案

1. 本地进程地址计算(直接解引用)

如果目标地址属于当前进程,可直接解引用获取指针指向的值,再添加偏移:

void aVoid()
{
    // 基地址(数值形式存储)
    DWORD64 basePtr = 0x000002586F08CE30;
    cout << hex << basePtr << endl;

    // 偏移量(数值形式存储)
    DWORD64 offset = 0x88;
    cout << hex << offset << endl;

    // 读取基地址指向的内存中的64位地址值
    DWORD64 targetBase = *(DWORD64*)basePtr;
    // 计算最终目标地址
    DWORD64 targetAddr = targetBase + offset;
    cout << hex << targetAddr << endl;    // 得到预期的0x25825C4C880
}

2. 远程进程地址计算(使用ReadProcessMemory)

如果目标地址属于其他进程(如代码中的游戏进程),必须通过ReadProcessMemory读取远程内存中的值:

// 假设已获取远程进程句柄hProc
DWORD64 basePtr = 0x000002586F08CE30;
DWORD64 offset = 0x88;

DWORD64 targetBase;
// 读取远程进程中basePtr地址的64位值
if (ReadProcessMemory(hProc, (LPVOID)basePtr, &targetBase, sizeof(targetBase), NULL))
{
    DWORD64 targetAddr = targetBase + offset;
    cout << hex << targetAddr << endl;
}

3. 代码中其他64位兼容性修正

  • GetModuleBaseAddress函数返回值类型从DWORD改为DWORD64,避免64位地址截断:
DWORD64 GetModuleBaseAddress(TCHAR* lpszModuleName, DWORD pID) {
    DWORD64 dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
    MODULEENTRY32 ModuleEntry32 = { 0 };
    ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
    
    if (Module32First(hSnapshot, &ModuleEntry32))
    {
        do {
            if (_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
            {
                dwModuleBaseAddress = (DWORD64)ModuleEntry32.modBaseAddr;
                break;
            }
        } while (Module32Next(hSnapshot, &ModuleEntry32));
    }
    CloseHandle(hSnapshot);
    return dwModuleBaseAddress;
}
  • GetPointerAddress函数中的地址变量改为DWORD64类型:
DWORD64 GetPointerAddress(HWND hwnd, DWORD64 gameBaseAddr, DWORD64 address, vector<DWORD64> offsets)
{
    DWORD pID = NULL;
    GetWindowThreadProcessId(hwnd, &pID);
    HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
    if (!phandle) return 0;

    DWORD64 pointeraddress = 0;
    ReadProcessMemory(phandle, (LPVOID*)(gameBaseAddr + address), &pointeraddress, sizeof(pointeraddress), 0);

    for (size_t i = 0; i < offsets.size() - 1; i++)
    {
        ReadProcessMemory(phandle, (LPVOID*)(pointeraddress + offsets[i]), &pointeraddress, sizeof(pointeraddress), 0);
    }
    pointeraddress += offsets.back();
    CloseHandle(phandle);
    return pointeraddress;
}

完整修正后的核心代码片段

int main() {
    HWND hWnd = FindWindowA(0, "Halo Wars: Definitive Edition");
    if (hWnd == 0) {
        cerr << "Could not find window." << endl;
        return 1;
    }

    DWORD PID;
    GetWindowThreadProcessId(hWnd, &PID);
    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
    if (!hProc) {
        cerr << "Cannot open process." << endl;
        return 1;
    }

    // 正确的64位地址偏移计算
    DWORD64 basePtr = 0x000002586F08CE30;
    DWORD64 offset = 0x88;

    cout << hex << "Base pointer: " << basePtr << endl;
    cout << hex << "Offset: " << offset << endl;

    DWORD64 targetBase;
    if (ReadProcessMemory(hProc, (LPVOID)basePtr, &targetBase, sizeof(targetBase), NULL))
    {
        DWORD64 targetAddr = targetBase + offset;
        cout << hex << "Target address: " << targetAddr << endl;
    }
    else
    {
        cerr << "Failed to read process memory." << endl;
    }

    CloseHandle(hProc);
    cin.get();
    return 0;
}

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:55:19