在Python中使用静态地址和偏移量从进程读取内存地址

在Python中使用静态地址和偏移量从进程读取内存地址,python,memory,process,Python,Memory,Process,我试图用Python读取另一个进程的内存,我有程序的静态地址和所有偏移量。我正在使用win32api来实现这一点。我已经可以用没有偏移量的地址读取进程内存,但我不知道如何使用偏移量 我已经在中尝试了该脚本,但它返回-1。我已将PROCESS\u ALL\u ACCESS更改为win32con.PROCESS\u VM\u READ,然后返回-1 如何在ReadProcessMemory中使用偏移量 以下是我正在使用的代码: 导入win32api 导入Win32进程 导入win32con 导入ct

我试图用Python读取另一个进程的内存,我有程序的静态地址和所有偏移量。我正在使用
win32api
来实现这一点。我已经可以用没有偏移量的地址读取进程内存,但我不知道如何使用偏移量

我已经在中尝试了该脚本,但它返回-1。我已将
PROCESS\u ALL\u ACCESS
更改为
win32con.PROCESS\u VM\u READ
,然后返回-1

如何在
ReadProcessMemory
中使用偏移量

以下是我正在使用的代码:

导入win32api
导入Win32进程
导入win32con
导入ctypes
将ctypes.wintypes导入为wintypes
def按进程名称获取进程(进程名称):
“”“查找给定进程的进程id。”
进程名称并返回进程id。“”
process_name=process_name.lower()
#列举所有进程
processs=win32process.enumprocess()
对于进程中的进程id:
#如果进程id与此程序相同,请跳过它
如果进程id==-1:
持续
#尝试读取进程内存
尝试:
p_handle=win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ,True,PROCESS_id)
#尝试阅读流程的模块
尝试:
modules=win32process.EnumProcessModules(p_句柄)
对于模块中的模块id:
name=str(win32process.GetModuleFileNameEx(p_句柄,模块id))
if name.lower().find(进程名称)!=-1:
返回进程id
最后:
win32api.CloseHandle(p_句柄)
除:
通过
def read_process_内存(进程id、地址、偏移量、数据大小=4):
p_handle=ctypes.windl.kernel32.OpenProcess(win32con.PROCESS\u VM\u READ,False,p\u id)
数据=ctypes.c单元(数据的大小)
bytesRead=ctypes.c单元(数据的大小)
当前地址=地址
如果偏移:
#做点什么来弥补这些不足
ctypes.windell.kernel32.ReadProcessMemory(p_句柄、当前_地址、ctypes.byref(数据)、ctypes.sizeof(数据)、ctypes.byref(ByteRead))
其他:
ctypes.windell.kernel32.ReadProcessMemory(p_句柄、当前_地址、ctypes.byref(数据)、ctypes.sizeof(数据)、ctypes.byref(ByteRead))
#关闭进程的句柄
ctypes.windell.kernel32.CloseHandle(p_handle)
返回数据.value
p_id=get_process_by_name(“program.exe”)
#如果没有补偿,效果很好
地址=0x2ADB1818
val=读取进程内存(p\U id,地址,无)
打印(val)
#没有指向正确的地址
地址=0x00571160
偏移量=[0xD84、0x1B8、0x38、0x5C、0x24、0xF4、0x1D08]
对于偏移中的偏移:
地址+=偏移量
val=读取处理内存(p\U id、地址、偏移量)
打印(val)

我已经找到了我所缺少的东西。我把地址翻译错了。它们是指向地址的指针,因此,当使用偏移量时,我需要读取它们,并将它们相互添加以访问我想要读取的值。另外,我需要使用程序的基址,我只需要返回模块的值

下面是上面的脚本,其中包含读取带有偏移量的进程内存所需的更改:

import win32api
import win32process
import win32con
import ctypes


def get_process_by_name(process_name):
    """Finds the process id of the given
    process name and returns the process id and its base address."""

    process_name = process_name.lower()

    # Enumerate all processes
    processes = win32process.EnumProcesses()

    for process_id in processes:
        # If process_id is the same as this program, skip it
        if process_id == -1:
            continue

        # Try to read the process memory
        try:
            h_process = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, True, process_id)

            # Try to read the modules of the process
            try:
                # modules is an array of base addresses of each module
                modules = win32process.EnumProcessModules(h_process)

                for base_address in modules:
                    # Get the name of the module
                    name = str(win32process.GetModuleFileNameEx(h_process, base_address))

                    # Compare it to the name of your program
                    if name.lower().find(process_name) != -1:
                        return process_id, base_address
            finally:
                win32api.CloseHandle(h_process)
        except:
            pass


def read_process_memory(process_id, address, offsets=[]):
    """Read a process' memory based on its process id, address and offsets.
    Returns the address without offsets and the value."""

    # The handle to the program's process
    # This will allow to use ReadProcessMemory
    h_process = ctypes.windll.kernel32.OpenProcess(win32con.PROCESS_VM_READ, False, p_id)

    # This is a pointer to the data you want to read
    # Use `data.value` to get the value at this pointer
    # In this case, this value is an Integer with 4 bytes
    data = ctypes.c_uint(0)

    # Size of the variable, it usually is 4 bytes
    bytesRead = ctypes.c_uint(0)

    # Starting address
    current_address = address

    if offsets:
        # Append a new element to the offsets array
        # This will allow you to get the value at the last offset
        offsets.append(None)

        for offset in offsets:
            # Read the memory of current address using ReadProcessMemory
            ctypes.windll.kernel32.ReadProcessMemory(h_process, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))

            # If current offset is `None`, return the value of the last offset
            if not offset:
                return current_address, data.value
            else:
                # Replace the address with the new data address
                current_address = data.value + offset

    else:
        # Just read the single memory address
        ctypes.windll.kernel32.ReadProcessMemory(h_process, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))

    # Close the handle to the process
    ctypes.windll.kernel32.CloseHandle(h_process)

    # Return a pointer to the value and the value
    # The pointer will be used to write to the memory
    return current_address, data.value


# Open the process
p_id, base_address = get_process_by_name("program.exe")

# The static address needs the program base_address
address = base_address + 0x00571160
offsets = [0xD84, 0x1B8, 0x38, 0x5C, 0x24, 0xF4, 0x1D08]
pointer_value, value = read_process_memory(p_id, address, offsets)
print(f"(Static Address) Value: {value}")

# Re-reading the memory with the last pointer
pointer_value, value = read_process_memory(p_id, pointer_value, None)
print(f"(Dynamic Address) Value: {value}")

您可以使用
ReadWriteMemory
模块,它更简单,并且您可以获得带有偏移量的指针