Reputation: 7
I'm building a Memory Scanner and in the middle of it I use VirtualQueryEx to get the size in bytes of the process. This is my VirtualQueryEx and MEMORY_BASIC_INFORMATION structure setups:
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
]
and before I call the function I also define some variables
mbi = MEMORY_BASIC_INFORMATION()
lpAdress = wintypes.LPVOID(None)
hProcess which is a OpenProcess() Handle
then I call it
VirtualQueryEx( hProcess, lpAdress, byref(mbi), sizeof(mbi))
and after I check the output of RegionSide field of MEMORY_BASIC_INFORMATION
mbi.RegionSize
the result is a crazy number of bytes like 135762539134976 which is so big that is probably a wrong value or at least something I dont understand, any ideas ?
Upvotes: 0
Views: 742
Reputation: 177901
Here's a verified working version. The numbers printed for my Python process agree with the SysInternals vmmap utility:
import ctypes as ct
from ctypes import wintypes as w
SIZE_T = ct.c_size_t
# https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-memory_basic_information
class MEMORY_BASIC_INFORMATION(ct.Structure):
_fields_ = [("BaseAddress", w.LPVOID),
("AllocationBase", w.LPVOID),
("AllocationProtect", w.DWORD),
("PartitionId", w.WORD),
("RegionSize", SIZE_T),
("State", w.DWORD),
("Protect", w.DWORD),
("Type", w.DWORD)]
# Allow this structure to print itself
def __repr__(self):
return f'MEMORY_BASIC_INFORMATION(BaseAddress={self.BaseAddress if self.BaseAddress is not None else 0:#x}, ' \
f'AllocationBase={self.AllocationBase if self.AllocationBase is not None else 0:#x}, ' \
f'AllocationProtect={self.AllocationProtect:#x}, ' \
f'PartitionId={self.PartitionId:#x}, ' \
f'RegionSize={self.RegionSize:#x}, ' \
f'State={self.State:#x}, ' \
f'Protect={self.Protect:#x}, ' \
f'Type={self.Type:#x})'
PMEMORY_BASIC_INFORMATION = ct.POINTER(MEMORY_BASIC_INFORMATION)
dll = ct.WinDLL('kernel32', use_last_error=True)
# https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualqueryex
VirtualQueryEx = dll.VirtualQueryEx
VirtualQueryEx.argtypes = w.HANDLE, w.LPCVOID, PMEMORY_BASIC_INFORMATION, SIZE_T
VirtualQueryEx.restype = SIZE_T
# https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess
GetCurrentProcess = dll.GetCurrentProcess
GetCurrentProcess.argtypes = ()
GetCurrentProcess.restype = w.HANDLE
h = GetCurrentProcess()
mbi = MEMORY_BASIC_INFORMATION()
# Starting at the beginning of the process' virtual memory,
# query the region and its size, then advance by the region size
# and continue to query until failure.
address = 0
while True:
result = VirtualQueryEx(h, address, ct.byref(mbi), ct.sizeof(mbi))
if result:
print(mbi)
address += mbi.RegionSize
else:
print(f'err={ct.get_last_error()}')
break
Output:
MEMORY_BASIC_INFORMATION(BaseAddress=0x0, AllocationBase=0x0, AllocationProtect=0x0, PartitionId=0x0, RegionSize=0x7ffe0000, State=0x10000, Protect=0x1, Type=0x0)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffe0000, AllocationBase=0x7ffe0000, AllocationProtect=0x2, PartitionId=0x0, RegionSize=0x1000, State=0x1000, Protect=0x2, Type=0x20000)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffe1000, AllocationBase=0x0, AllocationProtect=0x0, PartitionId=0x0, RegionSize=0x5000, State=0x10000, Protect=0x1, Type=0x0)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffe6000, AllocationBase=0x7ffe6000, AllocationProtect=0x2, PartitionId=0x0, RegionSize=0x1000, State=0x1000, Protect=0x2, Type=0x20000)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffe7000, AllocationBase=0x0, AllocationProtect=0x0, PartitionId=0x0, RegionSize=0x16bce19000, State=0x10000, Protect=0x1, Type=0x0)
...
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffaca6f6000, AllocationBase=0x7ffaca590000, AllocationProtect=0x80, PartitionId=0x0, RegionSize=0x1000, State=0x1000, Protect=0x4, Type=0x1000000)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffaca6f7000, AllocationBase=0x7ffaca590000, AllocationProtect=0x80, PartitionId=0x0, RegionSize=0x2000, State=0x1000, Protect=0x8, Type=0x1000000)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffaca6f9000, AllocationBase=0x7ffaca590000, AllocationProtect=0x80, PartitionId=0x0, RegionSize=0x9000, State=0x1000, Protect=0x4, Type=0x1000000)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffaca702000, AllocationBase=0x7ffaca590000, AllocationProtect=0x80, PartitionId=0x0, RegionSize=0x86000, State=0x1000, Protect=0x2, Type=0x1000000)
MEMORY_BASIC_INFORMATION(BaseAddress=0x7ffaca788000, AllocationBase=0x0, AllocationProtect=0x0, PartitionId=0x0, RegionSize=0x535868000, State=0x10000, Protect=0x1, Type=0x0)
err=87
Upvotes: 1