使用 Python 中的静态地址和偏移量从进程中读取内存地址 [英] Reading Memory Address from a process with a Static Address and Offsets in Python
问题描述
我正在尝试在 Python 中读取另一个进程的内存,并且我拥有程序的静态地址和所有偏移量.我正在使用 win32api
来做到这一点.我已经可以使用没有偏移的地址读取进程的内存,但我不知道如何使用偏移.
I'm trying to read another process' memory in Python and I have the static address of the program and all the offsets. I'm using the win32api
to do this. I can already read a process' memory with an address without offsets but I don't know how to use offsets.
我已经尝试过这个答案中的脚本,但它返回-1.我已将 PROCESS_ALL_ACCESS
更改为 win32con.PROCESS_VM_READ
,即使这样它也返回 -1.
I've already tried the script in this answer but it returns -1. I've changed the PROCESS_ALL_ACCESS
to win32con.PROCESS_VM_READ
and even then it returns -1.
如何在 ReadProcessMemory
中使用偏移量?
How do I use the offsets with ReadProcessMemory
?
这是我正在使用的代码:
Here is the code I'm using:
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)
推荐答案
我已经找到了我缺少的东西.我一直在解释错误的地址.它们是指向地址的指针,因此,在使用偏移量时,我需要读取它们,并将它们彼此相加以访问我想要读取的值.另外,我需要使用程序的基地址,为此我只需要返回模块的值.
I've figured out what I was missing. I've been interpreting the addresses wrong. They are pointers to the addresses and so, when using offsets I need to read them, and add them to one another to get access to the value I want to read. Also, I needed to use the base address of the program, for which I just needed to return the value of the module.
这是上面的脚本,其中包含必要的更改以读取具有偏移量的进程内存:
Here is the above script with the necessary changes to read a process' memory with offsets:
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}")
这篇关于使用 Python 中的静态地址和偏移量从进程中读取内存地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!