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

C++指针链读取异常:首次ReadProcessMemory返回无效地址求助

解决FindDMAAddy函数首次读取指针值异常的问题

看起来你遇到的核心问题是首次调用ReadProcessMemory后,地址变成了无意义的垃圾值,这大概率是读取操作失败但没被检测到导致的。结合你的描述和代码,我整理了几个关键排查点和修复方案:

1. 必须添加ReadProcessMemory的错误检查

你的代码完全没有检查读取操作是否成功——如果初始的0x58AC00在目标进程中是无效地址(比如进程内存布局变化、基址失效),ReadProcessMemory会直接失败,addr的值会保留未初始化的垃圾数据,正好对应你看到的异常结果。

修正后的代码要加入返回值检查,甚至可以获取错误码定位问题:

uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
    uintptr_t addr = ptr;
    for (unsigned int i = 0; i < offsets.size(); ++i)
    {
        if (!ReadProcessMemory(hProc, reinterpret_cast<LPCVOID>(addr), &addr, sizeof(addr), nullptr))
        {
            // 调试时可以打印错误码,方便定位问题
            DWORD errorCode = GetLastError();
            printf("Read failed at step %d, error: %lu\n", i, errorCode);
            return 0; // 返回无效值标记失败
        }
        addr += offsets[i];
    }
    return addr;
}

常见的错误码比如ERROR_INVALID_ADDRESS(输入地址无效)、ERROR_PARTIAL_COPY(读取权限不足),能帮你快速定位问题根源。

2. 确认初始基址0x58AC00的有效性

你提到之前函数正常运行,现在突然失效,最大的可能是目标程序更新后,静态基址发生了变化:

  • 如果0x58AC00是硬编码的模块基址,目标程序如果开启了ASLR(地址空间布局随机化),每次启动模块基址都会改变,不能直接用固定值,需要通过GetModuleHandleEx或EnumProcessModules动态获取目标模块的加载基址。
  • 如果是静态指针地址,目标程序更新后内存结构变化,这个指针的位置也会变动,需要用Cheat Engine等工具重新扫描确认正确的静态地址。

3. 验证偏移顺序和内存结构匹配

你的代码逻辑是:读取当前地址 → 添加偏移,这个顺序是符合多级DMA指针遍历的常规逻辑的,但需要确认你的偏移列表是否和目标内存结构完全匹配:

  • 比如第一个偏移0x374是否是一级指针读取后的偏移,而不是基址直接加的偏移?可以用Cheat Engine的指针扫描功能重新验证整个DMA链的偏移顺序是否正确。

4. 排查进程位数兼容性问题

如果你的注入程序和目标进程的位数不匹配(比如64位程序读取32位进程),sizeof(uintptr_t)会是8字节,而32位进程的指针只有4字节,这会导致ReadProcessMemory读取到多余的垃圾数据,直接破坏地址值。

  • 确保你的程序和目标进程的位数一致,或者根据目标进程的位数动态调整读取的字节数(比如32位进程读取4字节,64位读取8字节)。

额外调试建议

  • 在每次ReadProcessMemory前后打印addr的值,看哪一步出现异常;
  • 确认OpenProcess时是否申请了PROCESS_VM_READ权限,权限不足也会导致读取失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:01:45