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

如何处理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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:45:12