Read Process Memory doesn't seem to give the right value

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)

enter image description here

Upvotes: 0

Views: 604

Answers (1)

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:

  1. In Cheat Engine, search for 87949181 (hex for BRUH, which is trainer's name). Any data that you know will not change is also fine.
  2. Find the address that really corresponds to it. Should have 0x00000050, 0x01000000, 0x0000FF99, 0x99000000, 0x00001600, 0x212D0316, DC00002D after (see picture 1). This address is a pointer. In my case, it's 0x07D2F370 (picture 2).
  3. Double click on the address and do a pointer scan. In my case, the pointer address 0x07D2F218. This is a dynamic address that will change everytime, so you need to find the static address.
  4. You can find that "visualboyadvance-m.exe"+02224064 -> 07D2F218. The base address is therefore 0x07D2F218 - 0x02224064 = 0x9a0000. The static address offset for the data I'm searching for is 0x02224064. The offset for the trainer's name data is 0x158.

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:

Memory Viewer Picture 1

Cheat Engine Picture 2

================================================================

================================================================

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

Related Questions