如何处理VirtualQueryEx中RegionSize超出SIZE_T范围的问题?
解决VirtualQueryEx遍历内存时RegionSize溢出的问题
问题根源
你遇到的是32位程序在64位Windows系统下扫描64位进程内存的典型问题:
- 32位程序中
SIZE_T是32位类型,无法容纳64位内存区域的大小,导致meminfo.RegionSize被截断,出现看似远超范围的数值。 - 那个地址跳转的区域是Windows地址空间中用户态与内核态之间的空洞,属于不可访问的无效区域,不需要扫描。
解决方案
1. 改用64位编译(最优方案)
将程序编译为64位版本后:
SIZE_T会变为64位类型,能完整存储VirtualQueryEx返回的RegionSize值。- 直接用
addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize遍历即可,不会出现溢出问题。
2. 若必须使用32位程序扫描64位进程
通过判断地址范围跳过内核态空洞,避免无效遍历:
#include <windows.h> // Windows默认64位用户态地址上限 #define USER_MODE_ADDR_MAX 0x7FFFFFFFFFFFULL void ScanProcessMemory(HANDLE hProc) { MEMORY_BASIC_INFORMATION meminfo; UINT64 addr = 0; while (1) { // 调用VirtualQueryEx获取内存信息 if (!VirtualQueryEx(hProc, (LPCVOID)addr, &meminfo, sizeof(meminfo))) { DWORD err = GetLastError(); if (err == ERROR_INVALID_PARAMETER) { // 当前地址无效,跳转到高位用户态起始地址 addr = 0x100000000ULL; continue; } break; // 其他错误,终止遍历 } // 在这里处理当前内存块(比如检查权限、读取数据等) // 计算下一个地址,避免溢出 UINT64 next_addr = (UINT64)meminfo.BaseAddress + meminfo.RegionSize; if (next_addr > USER_MODE_ADDR_MAX) { // 即将进入内核态空洞,直接跳转至高位用户态区域 addr = 0x100000000ULL; } else { addr = next_addr; } // 遍历完所有用户态地址后终止 if (addr > USER_MODE_ADDR_MAX) { break; } } }
额外说明
那些看似超大的RegionSize其实是32位程序对64位数值的截断结果,并非真实的内存块大小。跳过内核态空洞后,就能正常遍历进程的所有有效用户态内存区域。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

