ReadProcessMemory avec ctypes
-
13-12-2019 - |
Question
Je travaille sur un petit entraîneur solitaire.Je ne sais pas pourquoi la fonction ReadProcessMemory ne fonctionne pas.Normalement, il renvoie False ou True mais dans ce cas rien.Le GetlastError() me donne le code d'erreur 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)
La solution
Vérifiez le commentaire de la communauté sur MSDN LireProcessMemory page, citation(sic):
W7 n'exécutera pas la mémoire du processus de lecture
Vous devrez peut-être vérifier vos autorisations d'accès pour "SE_DEBUG_NAME" pour le jeton de processus actuel.S'il n'est pas activé.Je l'ai activé.Cela doit bien sûr être fait en tant qu’administrateur.
Déclarez également entièrement les types de retour et utilisez le use_last_error
paramètre, où ctypes
mettra en cache le GetLastError()
valeur en interne directement après l'appel.Sinon, cela pourrait être incorrect.Si vous êtes sur un système 64 bits, SIZE_T et les pointeurs sont des valeurs 64 bits, ctypes doit donc connaître les types pour configurer correctement la pile pour l'appel.
...
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())
De plus, pour information, même avec tous les correctifs, j'obtiens la même valeur d'erreur, mais je n'ai pas pris la peine d'activer SE_DEBUG_NAME
.
RÉSOLU
La ligne suivante est le problème :
PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,PID).handle
win32api.OpenProcess
renvoie un temporaire PyHANDLE
qui est détruit et ferme la poignée une fois le handle récupéré.
La solution est d'utiliser :
PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,PID)
...
rPM(PROCESS.handle,ADDRESS1,ADDRESS2,64,0)
PROCESS
tient alors le PyHANDLE
objet et le handle reste valide.