After some pointerscaning I found base address, pointer and offsets:
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
}
=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
}