我需要知道如何在Python中监视内存地址及其值。 例如:我有一个用C编写的游戏。我想写一个Python脚本,它读取当前HitPoints的内存地址,并根据其值进行操作。
我已经可以使用CheatEngine获取内存地址,但我不知道如何在Python中使用它。
答案 0 :(得分:0)
这是read_process
功能。结果是bytes
(2.x str
)或ctypes结构数组。默认是从进程中读取1个字节。可选的dtype
参数必须是ctypes类型,例如ctypes.c_cint
或ctypes.Structure
子类。它读取给定类型的数组length
。
小心避免取消引用指针值。例如,如果传递dtype=c_char_p
,那么简单地索引结果数组将尝试取消引用当前进程中的远程指针,这可能会使Python崩溃。在previous answer中,如果你需要处理这种情况,我写了一个只读的RemotePointer
类。
import ctypes
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
PROCESS_VM_READ = 0x0010
SIZE_T = ctypes.c_size_t
PSIZE_T = ctypes.POINTER(SIZE_T)
def _check_bool(result, func, args):
if not result:
raise ctypes.WinError(error)
return args
kernel32.OpenProcess.errcheck = _check_bool
kernel32.OpenProcess.restype = wintypes.HANDLE
kernel32.OpenProcess.argtypes = (
wintypes.DWORD, # _In_ dwDesiredAccess
wintypes.BOOL, # _In_ bInheritHandle
wintypes.DWORD) # _In_ dwProcessId
kernel32.CloseHandle.errcheck = _check_bool
kernel32.CloseHandle.argtypes = (
wintypes.HANDLE,)
kernel32.ReadProcessMemory.errcheck = _check_bool
kernel32.ReadProcessMemory.argtypes = (
wintypes.HANDLE, # _In_ hProcess
wintypes.LPCVOID, # _In_ lpBaseAddress
wintypes.LPVOID, # _Out_ lpBuffer
SIZE_T, # _In_ nSize
PSIZE_T) # _Out_ lpNumberOfBytesRead
read_process
定义def read_process(pid, address, length=1, dtype=ctypes.c_char):
result = (dtype * length)()
nread = SIZE_T()
hProcess = kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
try:
kernel32.ReadProcessMemory(hProcess, address, result,
ctypes.sizeof(result),
ctypes.byref(nread))
finally:
kernel32.CloseHandle(hProcess)
if issubclass(dtype, ctypes.c_char):
return result.raw
return result
if __name__ == '__main__':
import os
class DType(ctypes.Structure):
_fields_ = (('x', ctypes.c_int),
('y', ctypes.c_double))
source = (DType * 2)(*[(42, 3.14),
(84, 2.72)])
pid = os.getpid()
address = ctypes.addressof(source)
sink = read_process(pid, address, 2, DType)
for din, dout in zip(source, sink):
assert din.x == dout.x
assert din.y == dout.y
size = ctypes.sizeof(source)
buf_source = ctypes.string_at(source, size)
buf_sink = read_process(pid, address, size)
assert buf_source == buf_sink