【问题标题】:Reading Memory Address from a process with a Static Address and Offsets in Python在 Python 中使用静态地址和偏移量从进程中读取内存地址
【发布时间】:2020-05-17 00:44:28
【问题描述】:

我正在尝试在 Python 中读取另一个进程的内存,并且我拥有程序的静态地址和所有偏移量。我正在使用win32api 来执行此操作。我已经可以使用没有偏移量的地址读取进程的内存,但我不知道如何使用偏移量。

我已经尝试过this answer 中的脚本,但它返回-1。我已将PROCESS_ALL_ACCESS 更改为win32con.PROCESS_VM_READ,即使这样它也返回-1。

如何使用ReadProcessMemory 的偏移量?

这是我正在使用的代码:

import win32api
import win32process
import win32con
import ctypes
import ctypes.wintypes as wintypes


def get_process_by_name(process_name):
    """Find the process id of the given
    process name and returns the process id."""

    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:
            p_handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, True, process_id)

            # Try to read the modules of the process
            try:
                modules = win32process.EnumProcessModules(p_handle)

                for module_id in modules:
                    name = str(win32process.GetModuleFileNameEx(p_handle, module_id))

                    if name.lower().find(process_name) != -1:
                        return process_id
            finally:
                win32api.CloseHandle(p_handle)
        except:
            pass


def read_process_memory(process_id, address, offsets, size_of_data=4):

    p_handle = ctypes.windll.kernel32.OpenProcess(win32con.PROCESS_VM_READ, False, p_id)

    data = ctypes.c_uint(size_of_data)
    bytesRead = ctypes.c_uint(size_of_data)

    current_address = address

    if offsets:
        # Do something to the offsets
        ctypes.windll.kernel32.ReadProcessMemory(p_handle, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))

    else:
        ctypes.windll.kernel32.ReadProcessMemory(p_handle, current_address, ctypes.byref(data), ctypes.sizeof(data), ctypes.byref(bytesRead))


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

    return data.value

p_id = get_process_by_name("program.exe")

# Without offsets it works fine
address = 0x2ADB1818
val = read_process_memory(p_id, address, None)
print(val)


# Does not point to the correct address
address = 0x00571160
offsets = [0xD84, 0x1B8, 0x38, 0x5C, 0x24, 0xF4, 0x1D08]
for offset in offsets:
    address += offset

val = read_process_memory(p_id, address, offsets)
print(val)

【问题讨论】:

    标签: python memory process


    【解决方案1】:

    我已经弄清楚我错过了什么。我一直在解释错误的地址。它们是指向地址的指针,因此,在使用偏移量时,我需要读取它们,并将它们相互添加以访问我想要读取的值。另外,我需要使用程序的基地址,我只需要返回模块的值。

    这是上面的脚本,其中包含必要的更改来读取带有偏移量的进程内存:

    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 模块,它更简单,并且您可以获得带有偏移量的指针
    猜你喜欢
    • 1970-01-01
    • 2015-07-09
    • 2016-12-30
    • 2015-10-14
    • 2020-02-24
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    相关资源
    最近更新 更多