【问题标题】:Python - how to get the value at a memory address?Python - 如何获取内存地址的值?
【发布时间】:2017-07-04 09:17:50
【问题描述】:

我正在尝试让 Python 从地址(例如 0x101BFFDC)获取值/数据,这是我通过使用游戏作弊引擎发现的。我做了很多研究,认为我需要使用ReadProcessMemory。但是,我尝试了几个示例都没有成功。

例如,我找到了以下代码:

from ctypes import *
from ctypes.wintypes import *
import struct

OpenProcess = windll.kernel32.OpenProcess
ReadProcessMemory = windll.kernel32.ReadProcessMemory
CloseHandle = windll.kernel32.CloseHandle

PROCESS_ALL_ACCESS = 0x1F0FFF

pid = 10684 # pid of the game
address = 0x101BFFDC # I put the address here

buffer = c_char_p(b"The data goes here")
val = c_int()
bufferSize = len(buffer.value)
bytesRead = c_ulong(0)

processHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
if ReadProcessMemory(processHandle, address, buffer, bufferSize, byref(bytesRead)):
    memmove(ctypes.byref(val), buffer, ctypes.sizeof(val))
    print("Success:" + str(val.value))
else:
    print("Failed.")

CloseHandle(processHandle)

我希望它给我 56 的值,这是我从作弊引擎得到的值。但是,它只打印“失败”。每次。

我怎样才能得到正确的值?

【问题讨论】:

标签: python windows memory ctypes cheat-engine


【解决方案1】:

这是 WinAPI ReadProcessMemory 的 ctypes 包装器。它需要进程 ID、基地址和字节大小来读取。它返回从目标进程读取的字节字符串。

如果allow_partial 为假,则整个地址范围必须是可读的,否则将失败并显示Windows 错误代码ERROR_PARTIAL_COPY。如果allow_partial 为真,则返回的字节串可能小于请求的字节数。

ctypes 定义

import ctypes
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

ERROR_PARTIAL_COPY = 0x012B
PROCESS_VM_READ = 0x0010

SIZE_T = ctypes.c_size_t
PSIZE_T = ctypes.POINTER(SIZE_T)

def _check_zero(result, func, args):
    if not result:
        raise ctypes.WinError(ctypes.get_last_error())
    return args

kernel32.OpenProcess.errcheck = _check_zero
kernel32.OpenProcess.restype = wintypes.HANDLE
kernel32.OpenProcess.argtypes = (
    wintypes.DWORD, # _In_ dwDesiredAccess
    wintypes.BOOL,  # _In_ bInheritHandle
    wintypes.DWORD) # _In_ dwProcessId

kernel32.ReadProcessMemory.errcheck = _check_zero
kernel32.ReadProcessMemory.argtypes = (
    wintypes.HANDLE,  # _In_  hProcess
    wintypes.LPCVOID, # _In_  lpBaseAddress
    wintypes.LPVOID,  # _Out_ lpBuffer
    SIZE_T,           # _In_  nSize
    PSIZE_T)          # _Out_ lpNumberOfBytesRead

kernel32.CloseHandle.argtypes = (wintypes.HANDLE,)

功能

def read_process_memory(pid, address, size, allow_partial=False):
    buf = (ctypes.c_char * size)()
    nread = SIZE_T()
    hProcess = kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
    try:
        kernel32.ReadProcessMemory(hProcess, address, buf, size,
            ctypes.byref(nread))
    except WindowsError as e:
        if not allow_partial or e.winerror != ERROR_PARTIAL_COPY:
            raise
    finally:
        kernel32.CloseHandle(hProcess)
    return buf[:nread.value]

示例

if __name__ == '__main__':
    import os

    buf = ctypes.create_string_buffer(b'eggs and spam')
    pid = os.getpid()
    address = ctypes.addressof(buf)
    size = len(buf.value)

    value = read_process_memory(pid, address, size)
    assert value == buf.value

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 2021-01-05
    • 1970-01-01
    • 2018-09-09
    相关资源
    最近更新 更多