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

VirtualQueryEx返回异常mbi.RegionSize值的ctypes问题排查

内存扫描器中VirtualQueryEx返回异常RegionSize的问题排查

问题描述

开发内存扫描器时,使用VirtualQueryEx获取进程内存区域大小,但MEMORY_BASIC_INFORMATION的RegionSize字段返回异常庞大的数值(如135762539134976),明显不符合预期。相关代码定义及调用逻辑如下:

原代码定义

VirtualQueryEx = windll.kernel32.VirtualQueryEx
VirtualQueryEx.restype = c_size_t

class MEMORY_BASIC_INFORMATION(Structure):
     _fields_ = [
    ("BaseAddress", c_ulonglong),
    ("AllocationBase", c_ulonglong),
    ("AllocationProtect", c_ulong),
    ("__alignment1", c_ulong),
    ("RegionSize", c_ulonglong),
    ("State", c_ulong),
    ("Protect", c_ulong),
    ("Type", c_ulong),
    ("__alignment2", c_ulong),
        ]

VirtualQueryEx.argtypes = [
 wintypes.HANDLE,                   # [in]  HANDLE                    hProcess
 wintypes.LPCVOID,                  # [in]  LPCVOID                   lpAdress
 POINTER(MEMORY_BASIC_INFORMATION), # [out] PMEMORY_BASIC_INFORMATION lpBuffer
 c_size_t,                          # [in]  SIZE_T                    lpBuffer
]

调用代码

mbi      = MEMORY_BASIC_INFORMATION()
lpAdress = wintypes.LPVOID(None)
# hProcess 为通过OpenProcess()获取的句柄
VirtualQueryEx( hProcess, lpAdress, byref(mbi), sizeof(mbi)) 

问题原因

核心问题是手动添加的对齐成员破坏了结构体的内存布局:

  • Windows系统中,MEMORY_BASIC_INFORMATION的内存对齐规则由系统自动处理,32位和64位系统下的对齐逻辑不同。
  • 原代码中手动添加的__alignment1和__alignment2成员,错误偏移了RegionSize字段的内存位置,导致读取到非目标区域的垃圾数据,从而出现异常大的数值。
  • 直接使用c_ulonglong作为指针类型不够严谨,应该用wintypes.LPVOID,它会根据系统位数自动适配32/64位指针长度。

修正方案

移除手动添加的对齐成员,让ctypes自动处理结构体对齐,并使用系统适配的类型定义结构体:

from ctypes import *
from ctypes import wintypes

VirtualQueryEx = windll.kernel32.VirtualQueryEx
VirtualQueryEx.restype = c_size_t

class MEMORY_BASIC_INFORMATION(Structure):
    _fields_ = [
        ("BaseAddress", wintypes.LPVOID),
        ("AllocationBase", wintypes.LPVOID),
        ("AllocationProtect", wintypes.DWORD),
        ("RegionSize", c_size_t),
        ("State", wintypes.DWORD),
        ("Protect", wintypes.DWORD),
        ("Type", wintypes.DWORD),
    ]

VirtualQueryEx.argtypes = [
    wintypes.HANDLE,
    wintypes.LPCVOID,
    POINTER(MEMORY_BASIC_INFORMATION),
    c_size_t,
]

额外注意事项

调用OpenProcess时,需确保获取的句柄包含PROCESS_QUERY_INFORMATION和PROCESS_VM_READ权限,否则VirtualQueryEx可能调用失败或返回无效数据。

内容的提问来源于stack exchange,提问作者João P 2018

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:39:25