Re: [ctypes-users] How come this is different?
Brought to you by:
theller
From: eryk s. <er...@gm...> - 2016-12-10 23:25:24
|
On Sat, Dec 10, 2016 at 9:30 PM, Michael C <mys...@gm...> wrote: > I am stuck on which line of information to feed to ReadmemoryProcess with > this, I think I properly retrieved the information from Virtualqueryex Here's an example that uses VirtualQueryEx to determine whether the specified address is allocated and readable. If so, it reads up to `count` double-precision floats via ReadProcessMemory, but it won't read past the allocated region size. import ctypes from ctypes import wintypes kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) PROCESS_VM_READ = 0x0010 PROCESS_QUERY_INFORMATION = 0x0400 MEM_COMMIT = 0x00001000 MEM_RESERVE = 0x00002000 MEM_FREE = 0x00010000 MEM_PRIVATE = 0x00020000 MEM_MAPPED = 0x00040000 MEM_IMAGE = 0x01000000 PAGE_NOACCESS = 0x00000001 PAGE_READONLY = 0x00000002 PAGE_READWRITE = 0x00000004 PAGE_WRITECOPY = 0x00000008 PAGE_EXECUTE = 0x00000010 PAGE_EXECUTE_READ = 0x00000020 PAGE_EXECUTE_READWRITE = 0x00000040 PAGE_EXECUTE_WRITECOPY = 0x00000080 PAGE_GUARD = 0x00000100 PAGE_NOCACHE = 0x00000200 PAGE_WRITECOMBINE = 0x00000400 PAGE_TARGETS_INVALID = 0x40000000 if not hasattr(wintypes, 'PVOID'): wintypes.PVOID = wintypes.LPVOID if not hasattr(wintypes, 'SIZE_T'): wintypes.SIZE_T = ctypes.c_size_t if not hasattr(wintypes, 'PSIZE_T'): wintypes.PSIZE_T = ctypes.POINTER(wintypes.SIZE_T) class MEMORY_BASIC_INFORMATION(ctypes.Structure): _fields_ = (('BaseAddress', wintypes.PVOID), ('AllocationBase', wintypes.PVOID), ('AllocationProtect', wintypes.DWORD), ('RegionSize', wintypes.SIZE_T), ('State', wintypes.DWORD), ('Protect', wintypes.DWORD), ('Type', wintypes.DWORD)) PMEMORY_BASIC_INFORMATION = ctypes.POINTER(MEMORY_BASIC_INFORMATION) def _check_zero(result, func, args): """ Check for zero or NULL return value. """ if not result: raise ctypes.WinError(ctypes.get_last_error()) return args # https://msdn.microsoft.com/en-us/library/ms683179 kernel32.GetCurrentProcess.restype = wintypes.HANDLE # https://msdn.microsoft.com/en-us/library/ms684320 kernel32.OpenProcess.errcheck = _check_zero kernel32.OpenProcess.restype = wintypes.HANDLE # https://msdn.microsoft.com/en-us/library/ms680553 kernel32.ReadProcessMemory.errcheck = _check_zero kernel32.ReadProcessMemory.argtypes = ( wintypes.HANDLE, # _In_ hProcess wintypes.LPCVOID, # _In_ lpBaseAddress wintypes.LPVOID, # _Out_ lpBuffer wintypes.SIZE_T, # _In_ nSize wintypes.PSIZE_T) # _Out_ lpNumberOfBytesRead # https://msdn.microsoft.com/en-us/library/aa366907 kernel32.VirtualQueryEx.errcheck = _check_zero kernel32.VirtualQueryEx.restype = wintypes.SIZE_T kernel32.VirtualQueryEx.argtypes = ( wintypes.HANDLE, # _In_ hProcess wintypes.LPCVOID, # _In_opt_ lpAddress PMEMORY_BASIC_INFORMATION, # _Out_ lpBuffer wintypes.SIZE_T) # _In_ dwLength if __name__ == '__main__': import sys dtype = ctypes.c_double if len(sys.argv) == 4: ph = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, int(sys.argv[1])) address = int(sys.argv[2], 16) count = int(sys.argv[3]) elif len(sys.argv) == 1: ph = kernel32.GetCurrentProcess() count = 10 source_array = (dtype * count)(*range(10)) address = ctypes.addressof(source_array) else: sys.exit('Usage: %s pid address count' % sys.argv[0]) mbi = MEMORY_BASIC_INFORMATION() kernel32.VirtualQueryEx(ph, address, ctypes.byref(mbi), ctypes.sizeof(mbi)) if mbi.State & MEM_FREE: sys.exit('Address not allocated') if mbi.State & MEM_RESERVE: sys.exit('Address reserved but not committed') if mbi.Protect & PAGE_NOACCESS: sys.exit('Address not accessible') block_size = min(mbi.RegionSize - (address - mbi.BaseAddress), ctypes.sizeof(dtype) * count) address_list = range(address, address + block_size, ctypes.sizeof(dtype)) input('Press enter to list %d values, or Ctrl+Break to quit\n' % len(address_list)) data = dtype() for address in address_list: kernel32.ReadProcessMemory(ph, address, ctypes.byref(data), ctypes.sizeof(data), None) print('%x: %f' % (address, data.value)) |