Reading memory with base address leading to .dll

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
phaser93
Posts: 2
Joined: 02 Apr 2020, 11:44

Reading memory with base address leading to .dll

02 Apr 2020, 12:13

Right now I am trying to read values from Idle Champions memory (IdleDragons.exe).
After some pointerscaning I found base address, pointer and offsets:
1.png
1.png (55.03 KiB) Viewed 1830 times
In this case, base address is linked to dll ("mono-2.0-bdwgc.dll"+0039FC38)
I managed to get base address of game (.exe) using this code:

Code: Select all

basez := getProcessBaseAddress("Idle Champions")

getProcessBaseAddress(WindowTitle, windowMatchMode := "3")    ;WindowTitle can be anything ahk_exe ahk_class etc
{
    if (windowMatchMode && A_TitleMatchMode != windowMatchMode)
    {
        mode := A_TitleMatchMode ; This is a string and will not contain the 0x prefix
        StringReplace, windowMatchMode, windowMatchMode, 0x ; remove hex prefix as SetTitleMatchMode will throw a run time error. This will occur if integer mode is set to hex and matchmode param is passed as an number not a string.
        SetTitleMatchMode, %windowMatchMode%    ;mode 3 is an exact match
    }
    WinGet, hWnd, ID, %WindowTitle%
    if mode
        SetTitleMatchMode, %mode%    ; In case executed in autoexec
    if !hWnd
        return ; return blank failed to find window
    return DllCall(A_PtrSize = 4     ; If DLL call fails, returned value will = 0
        ? "GetWindowLong"
        : "GetWindowLongPtr"
        , "Ptr", hWnd, "Int", -6, A_Is64bitOS ? "Int64" : "UInt")  
        ; For the returned value when the OS is 64 bit use Int64 to prevent negative overflow when AHK is 32 bit and target process is 64bit 
        ; however if the OS is 32 bit, must use UInt, otherwise the number will be huge (however it will still work as the lower 4 bytes are correct)      
        ; Note - it's the OS bitness which matters here, not the scripts/AHKs
} 
But I dont understand how to get the base address of this dll and how to reach 03B9C508 value.

=UPDATE=
Manged to do so using AutoHotkeyU32.exe. The problem was with AutoHotkeyU64.exe. It didnt work with this function:

Code: Select all

getModuleBaseAddress(program, module := "")
{
    WinGet, pid, pid, %program%
    if pid                              ; PROCESS_QUERY_INFORMATION + PROCESS_VM_READ 
        hProc := DllCall("OpenProcess", "UInt", 0x0400 | 0x0010 , "Int", 0, "UInt", pid)
    else return -2
    if !hProc
        return -3
    if (A_PtrSize = 4) ; AHK 32bit
    {
        DllCall("IsWow64Process", "Ptr", hProc, "Int*", result)
        if !result 
            return -5, DllCall("CloseHandle","Ptr",hProc)  ; AHK is 32bit and target process is 64 bit, this function wont work 
    }
    if (module = "")
    {        
        VarSetCapacity(mainExeNameBuffer, 2048 * (A_IsUnicode ? 2 : 1))
        DllCall("psapi\GetModuleFileNameEx", "Ptr", hProc, "UInt", 0
                    , "Ptr", &mainExeNameBuffer, "UInt", 2048 / (A_IsUnicode ? 2 : 1))
        mainExeFullPath := StrGet(&mainExeNameBuffer)
        ; mainExeName = main executable module of the process (will include full directory path)
    }
    size := VarSetCapacity(lphModule, 4)
    loop 
    {
        DllCall("psapi\EnumProcessModules", "Ptr", hProc, "Ptr", &lphModule
                , "UInt", size, "UInt*", reqSize)
        if ErrorLevel
            return -4, DllCall("CloseHandle","Ptr",hProc) 
        else if (size >= reqSize)
            break
        else 
            size := VarSetCapacity(lphModule, reqSize)    
    }
    VarSetCapacity(lpFilename, 2048 * (A_IsUnicode ? 2 : 1))
    loop % reqSize / A_PtrSize ; sizeof(HMODULE) - enumerate the array of HMODULEs
    {
        DllCall("psapi\GetModuleFileNameEx", "Ptr", hProc, "Ptr", numget(lphModule, (A_index - 1) * A_PtrSize)
                , "Ptr", &lpFilename, "UInt", 2048 / (A_IsUnicode ? 2 : 1))
        ; module will contain directory path as well e.g C:\Windows\syswow65\GDI32.dll
        moduleFullPath := StrGet(&lpFilename) 
        SplitPath, moduleFullPath, fileName ; strips the path so = GDI32.dll
        if (module = "" && mainExeFullPath = moduleFullPath) || (module != "" && module = filename)
        {
            VarSetCapacity(MODULEINFO, A_PtrSize = 4 ? 12 : 24)
            DllCall("psapi\GetModuleInformation", "Ptr", hProc, "Ptr", numget(lphModule, (A_index - 1) * A_PtrSize)
                , "Ptr", &MODULEINFO, "UInt", A_PtrSize = 4 ? 12 : 24)
            return numget(MODULEINFO, 0, "Ptr"), DllCall("CloseHandle","Ptr",hProc)
        }
    }
    return -1, DllCall("CloseHandle","Ptr",hProc) ; not found
}
I will appreciate if anyone will fix this since AHK64 is more preferable for me.
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: Reading memory with base address leading to .dll

03 Apr 2020, 11:05

This should work with ahk 64 bit.

Code: Select all

#SingleInstance Force
#Include <classMemory> ; Available from https://github.com/Kalamity/classMemory

if !A_IsAdmin 
{
        Run *RunAs "%A_ScriptFullPath%"
        exitapp 
}

if (_ClassMemory.__Class != "_ClassMemory")
{
    msgbox class memory not correctly installed. 
    ExitApp
}

mem := new _ClassMemory("ahk_exe IdleDragons.exe",, hProcessCopy)  ; Could probably use "Idle Champions" (from your example)

if !isObject(mem) 
{
    if (hProcessCopy = 0)
        msgbox The program isn't running (not found) or you passed an incorrect program identifier parameter. 
    else if (hProcessCopy = "")
        msgbox OpenProcess failed. If the target process has admin rights, then the script also needs to be ran as admin. _ClassMemory.setSeDebugPrivilege() may also be required. Consult A_LastError for more information.
    ExitApp
}

msgbox % "Game Base: " mem.BaseAddress

moduleBase := mem.getModuleBaseAddress("mono-2.0-bdwgc.dll")
msgbox % "Module Base: " moduleBase

ptr := [moduleBase + 0x0039FC38, "UInt", 0x64, 0x3C, 0x38, 0x18, 0x44]
value := mem.read(ptr*)
msgbox % "result: " value
phaser93
Posts: 2
Joined: 02 Apr 2020, 11:44

Re: Reading memory with base address leading to .dll

16 Jul 2022, 08:39

RHCP wrote:
03 Apr 2020, 11:05
This should work with ahk 64 bit.

Code: Select all

#SingleInstance Force
#Include <classMemory> ; Available from https://github.com/Kalamity/classMemory

if !A_IsAdmin 
{
        Run *RunAs "%A_ScriptFullPath%"
        exitapp 
}

if (_ClassMemory.__Class != "_ClassMemory")
{
    msgbox class memory not correctly installed. 
    ExitApp
}

mem := new _ClassMemory("ahk_exe IdleDragons.exe",, hProcessCopy)  ; Could probably use "Idle Champions" (from your example)

if !isObject(mem) 
{
    if (hProcessCopy = 0)
        msgbox The program isn't running (not found) or you passed an incorrect program identifier parameter. 
    else if (hProcessCopy = "")
        msgbox OpenProcess failed. If the target process has admin rights, then the script also needs to be ran as admin. _ClassMemory.setSeDebugPrivilege() may also be required. Consult A_LastError for more information.
    ExitApp
}

msgbox % "Game Base: " mem.BaseAddress

moduleBase := mem.getModuleBaseAddress("mono-2.0-bdwgc.dll")
msgbox % "Module Base: " moduleBase

ptr := [moduleBase + 0x0039FC38, "UInt", 0x64, 0x3C, 0x38, 0x18, 0x44]
value := mem.read(ptr*)
msgbox % "result: " value
Thank you for this code! It works with x64

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: peter_ahk and 361 guests