2

I'm trying to find the base address of render.dll used in the process process.exe. I have modified the code in this question, and I'm able to get a result for the base address of render.dll.

from ctypes import *
from ctypes.wintypes import *
import psutil


class MODULEENTRY32(Structure):
    _fields_ = [( 'dwSize', DWORD),
                ( 'th32ModuleID', DWORD),
                ( 'th32ProcessID', DWORD),
                ( 'GlblcntUsage', DWORD),
                ( 'ProccntUsage', DWORD),
                ( 'modBaseAddr', POINTER(BYTE)),
                ( 'modBaseSize', DWORD),
                ( 'hModule', HMODULE),
                ( 'szModule', c_char * 256),
                ( 'szExePath', c_char * 260)]


CreateToolhelp32Snapshot = windll.kernel32.CreateToolhelp32Snapshot
Module32First = windll.kernel32.Module32First
Module32Next = windll.kernel32.Module32Next
CloseHandle = windll.kernel32.CloseHandle
TH32CS_SNAPMODULE = 0x00000008
TH32CS_SNAPMODULE32 = 0x00000010


def getpid(processname):
    for proc in psutil.process_iter():
        if str(processname) in str(proc.name):
            return proc.pid


def GetModuleByName(name):
    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32 | TH32CS_SNAPMODULE, getpid('process.exe'))

    entry = MODULEENTRY32()
    entry.dwSize = sizeof(MODULEENTRY32)

    if Module32First(snapshot, pointer(entry)):
            while Module32Next(snapshot, entry):
                if entry.szModule == name:
                    CloseHandle(snapshot)
                    return entry.modBaseAddr
    CloseHandle(snapshot)
    return None

baseAddr = GetModuleByName('render.dll')
print baseAddr

Which results in <__main__.LP_c_byte object at 0x00000000023C9348>. I know this is to do with the result being a POINTER(BYTE) type, but I am not sure how to get from this type to a normal hex memory address that I can use to read the process memory at this location.

Community
  • 1
  • 1
adam b
  • 346
  • 1
  • 7
  • 17
  • `id(object)` will return the memory address of an object ... not sure why you want it as hex as im sure whatever is expecting an integer ... – Joran Beasley Sep 21 '15 at 17:12
  • I'm trying to find the memory address of `render.dll`, not the LP_c_byte object. The memory address I'm looking for should be contained within the LP_c_byte object, I'm just not sure how to retrieve it from that object. I wanted the hex value to compare with the hex value for `render.dll` that is shown in Process Hacker 2, but it's easy enough to convert between hex and integer so either is good for me. – adam b Sep 21 '15 at 18:12
  • You can use `byref(entry)` instead of `pointer(entry)`; i.e. you don't need to allocate an actual ctypes pointer object; just pass the address. The `Module32Next` call has a mistake; it's missing `byref` or `pointer` to pass the address of `entry`. – Eryk Sun Sep 22 '15 at 07:05
  • @eryksun I'm very new to memory reading, so could you please explain why passing `byref(entry)` is better than just passing `entry` to `Module32Next`? I get the same result either way. And I'm assuming passing `byref(entry)` instead of `pointer(entry)` to `Module32First` is just more efficient as there's no need to create the pointer object? Thanks. – adam b Sep 22 '15 at 10:14
  • 2
    Passing just `entry` is passing the structure by value, but you can clearly see in the [`Module32Next`](https://msdn.microsoft.com/en-us/library/ms684221) documentation that it expects a pointer. This happens to work in the x64 ABI since large structures are implicitly passed by reference. But in 32-bit x86 the structure is copied to the call stack, so Windows interprets the `dwSize` field as the pointer argument, which is an access violation. – Eryk Sun Sep 22 '15 at 18:39
  • 2
    You're also skipping the first module, which should be the process image (e.g. "process.exe"). Also matching the name should be case insensitive. – Eryk Sun Sep 22 '15 at 18:42
  • Thank you very much for your insight! – adam b Sep 22 '15 at 18:56

1 Answers1

1

I found an answer here. Turns out I had the same misunderstanding as the other poster and that using ctypes.addressof(baseAddr.contents) returns the correct memory address for the .dll.

Community
  • 1
  • 1
adam b
  • 346
  • 1
  • 7
  • 17
  • Why does it matter if you'll just be passing this pointer to `ReadProcessMemory`? Is this just for display? – Eryk Sun Sep 22 '15 at 06:58