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
相关产品推荐
相关产品推荐

