在Python中监视内存地址

时间:2016-07-04 14:28:33

标签: python windows

我需要知道如何在Python中监视内存地址及其值。 例如:我有一个用C编写的游戏。我想写一个Python脚本,它读取当前HitPoints的内存地址,并根据其值进行操作。

我已经可以使用CheatEngine获取内存地址,但我不知道如何在Python中使用它。

1 个答案:

答案 0 :(得分:0)

这是read_process功能。结果是bytes(2.x str)或ctypes结构数组。默认是从进程中读取1个字节。可选的dtype参数必须是ctypes类型,例如ctypes.c_cintctypes.Structure子类。它读取给定类型的数组length

小心避免取消引用指针值。例如,如果传递dtype=c_char_p,那么简单地索引结果数组将尝试取消引用当前进程中的远程指针,这可能会使Python崩溃。在previous answer中,如果你需要处理这种情况,我写了一个只读的RemotePointer类。

ctypes定义

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