8

im working on a little solitär trainer. I don't know why the function ReadProcessMemory doesn't work. Normally it returns a False or True but in that case nothing. The GetlastError() gives me the Errorcode 6.

#-*- coding: cp1252 -*-

import ctypes, win32ui, win32process ,win32api

PROCESS_ALL_ACCESS = 0x1F0FFF
HWND = win32ui.FindWindow(None,"Solitär").GetSafeHwnd()
print(HWND)
PID = win32process.GetWindowThreadProcessId(HWND)[1]
print(PID)
PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,PID).handle

rPM = ctypes.windll.kernel32.ReadProcessMemory
wPM = ctypes.windll.kernel32.WriteProcessMemory

ADDRESS1 = 0x00E97074
ADDRESS2 = ctypes.create_string_buffer(64)
pi = ctypes.pointer(ADDRESS2)
rPM(PROCESS,ADDRESS1,ADDRESS2,64,0)
print(ADDRESS2)
x=ctypes.windll.kernel32.GetLastError()
print(x)
John Doe
  • 136
  • 1
  • 2
  • 9
  • First thing to try is setting the return type of the functions in ctypes. If you don't set it defaults to int and you have bool. Second is that ctypes is really for C and isn't this a C++ library? If that is the case one might have to write C wrapper functions. – Brian Larsen Oct 03 '12 at 23:15
  • Python version (looks like 3.X)? Windows version? 32- or 64-bit? – Mark Tolonen Oct 04 '12 at 04:18
  • It is Python 3.2 and Win7 32bit! Which exact is a C++ library? – John Doe Oct 04 '12 at 07:39

1 Answers1

12

Check the community comment to the MSDN ReadProcessMemory page, quote(sic):

W7 wont run read process memory

You may need to check your access permissions for "SE_DEBUG_NAME" for the current processes token. If not enabled. Enabled it. This must be done as administrator of course.

Also fully declare the return types and use the use_last_error parameter, where ctypes will cache the GetLastError() value internally directly after the call. Otherwise, it may be incorrect. If you are on a 64-bit system, SIZE_T and pointers are 64-bit values so ctypes needs to know the types to set up the stack correctly for the call.

...
from ctypes import wintypes
...
rPM = ctypes.WinDLL('kernel32',use_last_error=True).ReadProcessMemory
rPM.argtypes = [wintypes.HANDLE,wintypes.LPCVOID,wintypes.LPVOID,ctypes.c_size_t,ctypes.POINTER(ctypes.c_size_t)]
rPM.restype = wintypes.BOOL
wPM = ctypes.WinDLL('kernel32',use_last_error=True).WriteProcessMemory
wPM.argtypes = [wintypes.HANDLE,wintypes.LPVOID,wintypes.LPCVOID,ctypes.c_size_t,ctypes.POINTER(ctypes.c_size_t)]
wPM.restype = wintypes.BOOL

ADDRESS1 = 0x00E97074
ADDRESS2 = ctypes.create_string_buffer(64)
bytes_read = ctypes.c_size_t()
print(rPM(PROCESS,ADDRESS1,ADDRESS2,64,ctypes.byref(bytes_read)))
print(ctypes.get_last_error())

Also, FYI, even with all the fixes I get the same error value, but I didn't go through the trouble of enabling SE_DEBUG_NAME.

SOLVED

The following line is the issue:

PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,PID).handle

win32api.OpenProcess returns a temporary PyHANDLE that gets destroyed and closes the handle after the handle is retrieved.

The solution is to use:

PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,PID)
...
rPM(PROCESS.handle,ADDRESS1,ADDRESS2,64,0)

PROCESS then holds the PyHANDLE object and the handle remains valid.

Community
  • 1
  • 1
Mark Tolonen
  • 132,868
  • 21
  • 152
  • 208
  • Hello, i tried DebugActiveProcess(PID). I don't know another function to active SE_DEBUG_NAME. Im working on a 32bit system. It seems tricky, I think here is a problem between win7 and ctypes. – John Doe Oct 04 '12 at 07:43
  • I wrote a helper function to enable the privilege and verified it was set through SysInternals ProcessExplorer. I had to be administrator to do it. I still got the same error. It's a challenge now, so I'll probably look at it again tonight, taking Python out of the picture and use C only. I've gotten this to work before, but not on Win7. – Mark Tolonen Oct 04 '12 at 13:52
  • Hello Mark, when i run this: http://pastebin.com/dCaKiFht is the output: ▼ According to the memoryviewer is the value 31 @ the Address1. Alt + 31 = ▼. So the Question is: Why dont run this with "Solitär" – John Doe Oct 04 '12 at 18:29
  • Oh No what a little mistakte! Thank you Very Much! – John Doe Oct 07 '12 at 12:29
  • No problem! On SO, click the up vote and accept checkbox to mark the answer as useful and correct. Thanks! – Mark Tolonen Oct 07 '12 at 16:26