Reputation: 371
I am trying to read memory from a process (gameboy advance emulator) in Python using ReadProcessMemory. There is a memory viewer and I am supposed to get 81 at 0xD273 (see picture). I am new to this, I tried to do everything correctly by adding reference in the ReadProcessMemory, but there might be some things that are wrong. I am pretty sure I have the right process id since it matches the one in the task manager.
When I run my code, I get random byte values that are different everytime. 15, 255, 11, 195, but I think I should be getting 81.
I need to use python 32-bit to run the script otherwise I get error 299 (ERROR_PARTIAL_COPY).
Is there something that I'm doing wrong? I don’t specify the base address but I assumed it’s handled by the processHandle
.
Here is my code and an example of the output:
result: 1, err code: 0, bytesRead: 1
data: 0000000000000015h
21
import ctypes as c
from ctypes import wintypes as w
import psutil
# Must use py -3-32 vba_script.py
vba_process_id = [p.pid for p in psutil.process_iter() if "visualboyadvance" in p.name()][0]
pid = vba_process_id # I assume you have this from somewhere.
k32 = c.WinDLL('kernel32', use_last_error=True)
OpenProcess = k32.OpenProcess
ReadProcessMemory = k32.ReadProcessMemory
CloseHandle = k32.CloseHandle
processHandle = OpenProcess(0x10, False, pid)
addr = c.c_void_p(0xD273)
dataLen = 8
data = c.c_byte()
bytesRead = c.c_byte()
result = ReadProcessMemory(processHandle, c.byref(addr), c.byref(data), c.sizeof(data), c.byref(bytesRead))
e = c.get_last_error()
print('result: {}, err code: {}, bytesRead: {}'.format(result,e,bytesRead.value))
print('data: {:016X}h'.format(data.value))
print(data.value)
CloseHandle(processHandle)
Upvotes: 0
Views: 604
Reputation: 371
After reading @jasonharper answer, I found a way to get the actual address in the memory.
To get them, I used Cheat Engine, here was my procedure:
After opening the process, to search in the memory, you can have a code like this:
base_addr = 0x9a0000 # "visualboyadvance-m.exe"
static_addr_offset = 0x02224064
address = base_addr + static_addr_offset + 0x158
k32 = c.WinDLL('kernel32', use_last_error=True)
buffer = c.create_string_buffer(buffer_size)
buffer_size=32
bytes_read = c.c_ulong(0)
if k32.ReadProcessMemory(processHandle, address, buffer, buffer_size, c.byref(bytes_read)):
data = c.c_uint32.from_buffer(buffer)
print(f"data: {data .value:X}")
This returns the right data that I'm looking for: data: 87949181
.
Here are the pictures:
================================================================
================================================================
Bonus:
The base address will change if you close the game and you will need to find it back everytime. There is some way of doing way it by getting the module with the name of the process pname
. You can get it easily with psutil.
import win32process
import psutils
vba_process = [p for p in psutil.process_iter() if "visualboyadvance" in p.name()][0]
pid = vba_process.pid
pname = vba_process.name
k32 = c.WinDLL('kernel32', use_last_error=True)
processHandle = k32.OpenProcess(0x10, False, pid)
modules = win32process.EnumProcessModules(processHandle)
for module in modules:
moduleFileName = win32process.GetModuleFileNameEx(processHandle, module)
if pname in moduleFileName:
base_address = module
print("Success: Got Base Address:", hex(base_address))
Success: Got Base Address: 0x9a0000
Edit: Found how to get base address of process automatically
Upvotes: 1