Re: How come this is different?
eryk sun <[email protected]> Sat, 10 Dec 2016 14:30:10 +0000
| Newsgroups | gmane.comp.python.ctypes |
|---|---|
| Message-ID | <CACL+1av-n1Ug5Ecx3HJ-seuH=_VU3rxJbGs-0iDfTXjZKA7xsw@mail.gmail.com> |
On Sat, Dec 10, 2016 at 12:12 AM, Michael C <[email protected]> wrote: > Here is my entire current work in progress: > > #import modules > import ctypes > import time [snip] Here's a working example for ReadProcessMemory. import ctypes from ctypes import wintypes kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) PROCESS_VM_READ = 0x0010 PROCESS_QUERY_INFORMATION = 0x0400 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) 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 if __name__ == '__main__': import sys if len(sys.argv) == 4: ph = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, int(sys.argv[1])) base_address = int(sys.argv[2]) block_size = int(sys.argv[3]) elif len(sys.argv) == 1: ph = kernel32.GetCurrentProcess() source_array = (wintypes.DWORD * 10)(*range(10)) base_address = ctypes.addressof(source_array) block_size = ctypes.sizeof(source_array) else: sys.exit('Usage: %s pid base_address block_size' % sys.argv[0]) address_list = range(base_address, base_address + block_size, ctypes.sizeof(wintypes.DWORD)) data = wintypes.DWORD() for address in address_list: kernel32.ReadProcessMemory(ph, address, ctypes.byref(data), ctypes.sizeof(data), None) print('%x: %d' % (address, data.value)) This script defaults to a demo that reads an array of DWORD values from its own process. You can also provide it the PID, base address, and block size to read from another process. You could extend this with another option to configure the type of data read (e.g. char, float) based on simple ctypes format codes, e.g. "L" for a DWORD, where "L" is the value of `wintypes.DWORD._type_`. Or instead follow WinDbg conventions (e.g. db, dw, dd). Note that I assign an errcheck function for the OpenProcess and ReadProcessMemory function pointers. In this case both use the same _check_zero function, which raises an OSError (or WindowsError in 2.x) when the call fails. Idiomatic Python programming uses exceptions for error handling and resource management (i.e. try/except/finally). Get the error code from the exception's `winerror` attribute when handling it. Here's the complete list of WinAPI error codes: https://msdn.microsoft.com/en-us/library/ms681381 ------------------------------------------------------------------------------ Developer Access Program for Intel Xeon Phi Processors Access to Intel Xeon Phi processor-based developer platforms. With one year of Intel Parallel Studio XE. Training and support from Colfax. Order your platform today.http://sdm.link/xeonphi