Hello Tim, everyone: I actually have a semi-working scanner, but I can't figure out why it doesn't return nearly as many addresses as Cheat Engine does.(for scan run #1) Let's say I am scanning the Calculator that comes with Windows.
Please have a look!
import ctypes from ctypes.wintypes import WORD, DWORD, LPVOID import psutil import sys def main(): PID = int(input('enter PID')) target_value = int(input('new scan value')) # a simple list to contain all the addresses the code finds. hit_pool = list() # calls the function to scan the application's memory, and then returns # the addresses found to contain the target value, back into the list. hit_pool = First_scan(hit_pool, target_value, PID) # prints all the addresses to take a look. print(hit_pool) # calls the second scan function by passing it the hit_pool, and then # scan for the value present in the address, compare it with the new # target value, if they are differnt, the address is removed. while target_value != -999: target_value = int(input('new scan value')) hit_pool = Second_scan(hit_pool, target_value, PID) print('done.') ##print(hit_pool) def First_scan(hit_pool, target_value, PID): ############################################################### ############################################################### ############################################################### ## I think this part works properly! ############################################################### ############################################################### PVOID = LPVOID SIZE_T = ctypes.c_size_t # https://msdn.microsoft.com/en-us/library/aa383751#DWORD_PTR if ctypes.sizeof(ctypes.c_void_p) == ctypes.sizeof(ctypes.c_ulonglong): DWORD_PTR = ctypes.c_ulonglong elif ctypes.sizeof(ctypes.c_void_p) == ctypes.sizeof(ctypes.c_ulong): DWORD_PTR = ctypes.c_ulong class SYSTEM_INFO(ctypes.Structure): """https://msdn.microsoft.com/en-us/library/ms724958""" class _U(ctypes.Union): class _S(ctypes.Structure): _fields_ = (('wProcessorArchitecture', WORD), ('wReserved', WORD)) _fields_ = (('dwOemId', DWORD), # obsolete ('_s', _S)) _anonymous_ = ('_s',) _fields_ = (('_u', _U), ('dwPageSize', DWORD), ('lpMinimumApplicationAddress', LPVOID), ('lpMaximumApplicationAddress', LPVOID), ('dwActiveProcessorMask', DWORD_PTR), ('dwNumberOfProcessors', DWORD), ('dwProcessorType', DWORD), ('dwAllocationGranularity', DWORD), ('wProcessorLevel', WORD), ('wProcessorRevision', WORD)) _anonymous_ = ('_u',) LPSYSTEM_INFO = ctypes.POINTER(SYSTEM_INFO) Kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) Kernel32.GetSystemInfo.restype = None Kernel32.GetSystemInfo.argtypes = (LPSYSTEM_INFO,) sysinfo = SYSTEM_INFO() Kernel32.GetSystemInfo(ctypes.byref(sysinfo)) PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 Process = Kernel32.OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, False, PID) print('process:', Process) class MEMORY_BASIC_INFORMATION(ctypes.Structure): """https://msdn.microsoft.com/en-us/library/aa366775""" _fields_ = (('BaseAddress', PVOID), ('AllocationBase', PVOID), ('AllocationProtect', DWORD), ('RegionSize', SIZE_T), ('State', DWORD), ('Protect', DWORD), ('Type', DWORD)) mbi = MEMORY_BASIC_INFORMATION() print('VirtualQueryEx ran properly?',Kernel32.VirtualQueryEx(Process, \ sysinfo.lpMinimumApplicationAddress, ctypes.byref(mbi),ctypes.sizeof(mbi))) ############################################################### ############################################################### ############################################################### ## I think the following part has a bug ############################################################### ############################################################### ReadProcessMemory = Kernel32.ReadProcessMemory ## MEM_COMMIT = 0x00001000; PAGE_READWRITE = 0x04; ####### ####### ####### ####### IMPORTANT! I know I am supposed to initiate buffer ####### with something, but I can't work out what to put ####### down! buffer = ctypes.c_double() nread = SIZE_T() ####### ####### ####### ####### ##start = ctypes.c_void_p(mbi.BaseAddress) current_address = sysinfo.lpMinimumApplicationAddress end_address = sysinfo.lpMaximumApplicationAddress ####### ####### ####### ####### This is where the real memory scanning happens! # this variable keeps track of how many addresses have been found! hit_count = 0 while current_address < end_address: #### this line figures out if this chunk of memory can be scanned! Kernel32.VirtualQueryEx(Process, \ current_address, ctypes.byref(mbi),ctypes.sizeof(mbi)) #### this line figures out if this chunk of memory can be scanned! if mbi.Protect == PAGE_READWRITE and mbi.State == MEM_COMMIT : print('This region can be scanned!') index = current_address end = current_address + mbi.RegionSize - 7 #### finally, the scanning part! for address in range(index, end, 1): if ReadProcessMemory(Process, address, ctypes.byref(buffer), \ ctypes.sizeof(buffer), ctypes.byref(nread)): #### compares the values to the target value #### I haven't worked out how to 'round' if buffer.value < (target_value + 1) and \ buffer.value > (target_value - 1): print(buffer, buffer.value, address, 'hit:', hit_count) hit_count += 1 #### add the address to the list! hit_pool.append(i) else: print('else happend.') input('program pause because ReadProcessMemory happened.') current_address += mbi.RegionSize print(hit_count) return hit_pool def Second_scan(hit_pool, target_value, PID): ############################################################### ############################################################### ############################################################### ## I think this part works properly! ############################################################### ############################################################### PVOID = LPVOID SIZE_T = ctypes.c_size_t # https://msdn.microsoft.com/en-us/library/aa383751#DWORD_PTR if ctypes.sizeof(ctypes.c_void_p) == ctypes.sizeof(ctypes.c_ulonglong): DWORD_PTR = ctypes.c_ulonglong elif ctypes.sizeof(ctypes.c_void_p) == ctypes.sizeof(ctypes.c_ulong): DWORD_PTR = ctypes.c_ulong class SYSTEM_INFO(ctypes.Structure): """https://msdn.microsoft.com/en-us/library/ms724958""" class _U(ctypes.Union): class _S(ctypes.Structure): _fields_ = (('wProcessorArchitecture', WORD), ('wReserved', WORD)) _fields_ = (('dwOemId', DWORD), # obsolete ('_s', _S)) _anonymous_ = ('_s',) _fields_ = (('_u', _U), ('dwPageSize', DWORD), ('lpMinimumApplicationAddress', LPVOID), ('lpMaximumApplicationAddress', LPVOID), ('dwActiveProcessorMask', DWORD_PTR), ('dwNumberOfProcessors', DWORD), ('dwProcessorType', DWORD), ('dwAllocationGranularity', DWORD), ('wProcessorLevel', WORD), ('wProcessorRevision', WORD)) _anonymous_ = ('_u',) LPSYSTEM_INFO = ctypes.POINTER(SYSTEM_INFO) Kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) Kernel32.GetSystemInfo.restype = None Kernel32.GetSystemInfo.argtypes = (LPSYSTEM_INFO,) sysinfo = SYSTEM_INFO() Kernel32.GetSystemInfo(ctypes.byref(sysinfo)) PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 Process = Kernel32.OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, False, PID) print('process:', Process) class MEMORY_BASIC_INFORMATION(ctypes.Structure): """https://msdn.microsoft.com/en-us/library/aa366775""" _fields_ = (('BaseAddress', PVOID), ('AllocationBase', PVOID), ('AllocationProtect', DWORD), ('RegionSize', SIZE_T), ('State', DWORD), ('Protect', DWORD), ('Type', DWORD)) mbi = MEMORY_BASIC_INFORMATION() print('VirtualQueryEx ran properly?',Kernel32.VirtualQueryEx(Process, \ sysinfo.lpMinimumApplicationAddress, ctypes.byref(mbi),ctypes.sizeof(mbi))) ############################################################### ############################################################### ############################################################### ## I think the following part has a bug ############################################################### ############################################################### ReadProcessMemory = Kernel32.ReadProcessMemory MEM_COMMIT = 0x00001000; PAGE_READWRITE = 0x04; ####### ####### ####### ####### IMPORTANT! I know I am supposed to initiate buffer ####### with something, but I can't work out what to put ####### down! buffer = ctypes.c_double() nread = SIZE_T() ####### ####### ####### ####### hit_count = 0 hit_pool_2 = list() for address in hit_pool: Kernel32.VirtualQueryEx(Process, \ address, ctypes.byref(mbi),ctypes.sizeof(mbi)) if mbi.Protect == PAGE_READWRITE and mbi.State == MEM_COMMIT : print('This region can be scanned!') if ReadProcessMemory(Process, address, ctypes.byref(buffer), \ ctypes.sizeof(buffer), ctypes.byref(nread)): if buffer.value < (target_value + 1) and \ buffer.value > (target_value - 1): print(i,'OVERKILL!!!') hit_pool_2.append(address) else: print('else happend.') input('program pause because ReadProcessMemory happened.') else: '2nd run VirtualQueryEx error' hit_pool = hit_pool_2 print('Hit_pool', hit_pool) return hit_pool_2 main()
_______________________________________________ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32