Jump to content

_MemoryGetBaseAddress, calculating the pointers


Recommended Posts

Here's my CE table for the value i want to calculate...

<CheatTable>

<CheatEntries>

<CheatEntry>

<Description>hp</Description>

<Address>00000000</Address>

<Type>2</Type>

<Pointer>

<Offsets>

<Offset>0278</Offset>

<Offset>0028</Offset>

</Offsets>

<Address>009E7C8C</Address>

<InterpretableAddress>ElementClient.exe+005E7C8C</InterpretableAddress>

</Pointer>

</CheatEntry>

</CheatEntries>

</CheatTable>

and a representation of how it appears in CE in order from top to bottom:

29E99288 <target address

address of pointer.......033C2030...............................offset(hex) 278

address of pointer....ElementClient.exe+005E7C8C...offset(hex) 28

I have a general understanding that the Element line points to the next one up, then the next one up points to the target...

I've searched and found and modified this example but i can't get it to work:

while 1

$baseADDR = _MemoryGetBaseAddress($ProcessID, 1);;gets the base address after finding the ID

$StaticOffset = Dec("005E7C8C");;the offset for the green address

$CharHPPtrOffset = "278";;2nd level pointer offset

$CharHPOffset = "28";;1st level pointer offset

$CalcADDR = "0x" & Hex($baseADDR + $StaticOffset);;2nd level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find 1st level pointer

$CalcADDR = "0x" & Hex($value + $CharHPPtrOffset);;1st level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find address of value

$HPADDR = "0x" & Hex($value + $CharHPOffset);;address of value

$HP = _MemoryRead($HPADDR,$ProcessID);;the value

tooltip($HP,0,0)

tooltip($baseADDR,0,100)

wend

This reports 0 for both which is the wrong value.......... if i replace everything from while to wend with this:

while 1

$hp = _MemoryRead(0x29E99288, $DllInformation)

tooltip($HP,0,0)

wend

it DOES work... so it has to be the code from above going wrong.. seems it fails from the first baseADDR, and i don't know why... i included the memory udf and everything... from http://www.autoitscript.com/forum/index.ph...ic=78834&hl

PLEASE HELP..

PS i've tried swapping the 28 and 278 to no avail.

For those that really want to dig in, here's the script in entirety... "getbase.au3" is the memory.au3 from the above listed thread..

#include <NomadMemory.au3>

#include <getbase.au3>

HotKeySet("{PAUSE}", "Pause")

HotKeySet("^c", "MyExit")

Hotkeyset("^f", "Forage")

Opt("WinTitleMatchMode", 4)

Opt("TrayIconDebug",1)

Global $ProcessID = WinGetProcess("ClassName=XYElementClient Window","")

If $ProcessID = -1 Then

MsgBox(4096, "ERROR", "Failed to detect ESO window.")

EndIf

Global $DllInformation = _MemoryOpen($ProcessID)

Global $Pause

Global $Forage

while 1

$baseADDR = _MemoryGetBaseAddress($ProcessID, 1);;gets the base address after finding the ID

$StaticOffset = Dec("28");;the offset for the green address

$CharHPPtrOffset = "278";;2nd level pointer offset

$CharHPOffset = "005E7C8C";;1st level pointer offset

$CalcADDR = "0x" & Hex($baseADDR + $StaticOffset);;2nd level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find 1st level pointer

$CalcADDR = "0x" & Hex($value + $CharHPPtrOffset);;1st level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find address of value

$HPADDR = "0x" & Hex($value + $CharHPOffset);;address of value

$HP = _MemoryRead($HPADDR,$ProcessID);;the value

tooltip($HP,0,0)

tooltip($baseADDR,0,100)

sleep(500)

WEnd

Func Pause()

$Pause = NOT $Pause

While $Pause

Sleep(5000)

WEnd

winactivate("口袋西游")

WinWaitActive("口袋西游")

send("{ESC}")

EndFunc

Func Forage()

$Forage = NOT $Forage

while $Forage

winactivate("口袋西游")

WinWaitActive("口袋西游")

mouseclick("LEFT",407, 365,1)

sleep(25000)

WEnd

EndFunc

Func MyExit()

_MemoryClose($DllInformation)

If @Error Then

MsgBox(4096, "ERROR", "Failed to close memory.")

Exit

EndIf

EndFunc

Edited by crazedwombat
Link to comment
Share on other sites

Here's my CE table for the value i want to calculate...

<CheatTable>

<CheatEntries>

<CheatEntry>

<Description>hp</Description>

<Address>00000000</Address>

<Type>2</Type>

<Pointer>

<Offsets>

<Offset>0278</Offset>

<Offset>0028</Offset>

</Offsets>

<Address>009E7C8C</Address>

<InterpretableAddress>ElementClient.exe+005E7C8C</InterpretableAddress>

</Pointer>

</CheatEntry>

</CheatEntries>

</CheatTable>

and a representation of how it appears in CE in order from top to bottom:

29E99288 <target address

address of pointer.......033C2030...............................offset(hex) 278

address of pointer....ElementClient.exe+005E7C8C...offset(hex) 28

I have a general understanding that the Element line points to the next one up, then the next one up points to the target...

I've searched and found and modified this example but i can't get it to work:

while 1

$baseADDR = _MemoryGetBaseAddress($ProcessID, 1);;gets the base address after finding the ID

$StaticOffset = Dec("005E7C8C");;the offset for the green address

$CharHPPtrOffset = "278";;2nd level pointer offset

$CharHPOffset = "28";;1st level pointer offset

$CalcADDR = "0x" & Hex($baseADDR + $StaticOffset);;2nd level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find 1st level pointer

$CalcADDR = "0x" & Hex($value + $CharHPPtrOffset);;1st level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find address of value

$HPADDR = "0x" & Hex($value + $CharHPOffset);;address of value

$HP = _MemoryRead($HPADDR,$ProcessID);;the value

tooltip($HP,0,0)

tooltip($baseADDR,0,100)

wend

This reports 0 for both which is the wrong value.......... if i replace everything from while to wend with this:

while 1

$hp = _MemoryRead(0x29E99288, $DllInformation)

tooltip($HP,0,0)

wend

it DOES work... so it has to be the code from above going wrong.. seems it fails from the first baseADDR, and i don't know why... i included the memory udf and everything... from http://www.autoitscript.com/forum/index.ph...ic=78834&hl

PLEASE HELP..

PS i've tried swapping the 28 and 278 to no avail.

For those that really want to dig in, here's the script in entirety... "getbase.au3" is the memory.au3 from the above listed thread..

#include <NomadMemory.au3>

#include <getbase.au3>

HotKeySet("{PAUSE}", "Pause")

HotKeySet("^c", "MyExit")

Hotkeyset("^f", "Forage")

Opt("WinTitleMatchMode", 4)

Opt("TrayIconDebug",1)

Global $ProcessID = WinGetProcess("ClassName=XYElementClient Window","")

If $ProcessID = -1 Then

MsgBox(4096, "ERROR", "Failed to detect ESO window.")

EndIf

Global $DllInformation = _MemoryOpen($ProcessID)

Global $Pause

Global $Forage

while 1

$baseADDR = _MemoryGetBaseAddress($ProcessID, 1);;gets the base address after finding the ID

$StaticOffset = Dec("28");;the offset for the green address

$CharHPPtrOffset = "278";;2nd level pointer offset

$CharHPOffset = "005E7C8C";;1st level pointer offset

$CalcADDR = "0x" & Hex($baseADDR + $StaticOffset);;2nd level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find 1st level pointer

$CalcADDR = "0x" & Hex($value + $CharHPPtrOffset);;1st level pointer

$value = "0x" & Hex(_MemoryRead($CalcADDR,$ProcessID));;calc to find address of value

$HPADDR = "0x" & Hex($value + $CharHPOffset);;address of value

$HP = _MemoryRead($HPADDR,$ProcessID);;the value

tooltip($HP,0,0)

tooltip($baseADDR,0,100)

sleep(500)

WEnd

Func Pause()

$Pause = NOT $Pause

While $Pause

Sleep(5000)

WEnd

winactivate("口袋西游")

WinWaitActive("口袋西游")

send("{ESC}")

EndFunc

Func Forage()

$Forage = NOT $Forage

while $Forage

winactivate("口袋西游")

WinWaitActive("口袋西游")

mouseclick("LEFT",407, 365,1)

sleep(25000)

WEnd

EndFunc

Func MyExit()

_MemoryClose($DllInformation)

If @Error Then

MsgBox(4096, "ERROR", "Failed to close memory.")

Exit

EndIf

EndFunc

I'm assuming you need to find the pointer of an address? Any kernel debugger is capable of this. Even Cheat Engine.

Link to comment
Share on other sites

I'm assuming you need to find the pointer of an address? Any kernel debugger is capable of this. Even Cheat Engine.

i have the pointer.. that's the point... i can't get autoit to calculate the pointers... i don't want to cut and paste from CE every time i restart the game... and i don't want to use some old convoluted 50000 step code to do it... i heard tihs memory.au3 works but i can't figure out the syntax i guess...

Maybe understanding the equation will help me, is it like this?

29E99288 <target address

address of pointer.......033C2030...............................offset(hex) 278

address of pointer....ElementClient.exe+005E7C8C...offset(hex) 28

elementclient.exe+005E7C8C+28=033C2030

then

033C2030+278=29E99288

???????????????????????????????????????????????

Edited by crazedwombat
Link to comment
Share on other sites

i have the pointer.. that's the point... i can't get autoit to calculate the pointers... i don't want to cut and paste from CE every time i restart the game... and i don't want to use some old convoluted 50000 step code to do it... i heard tihs memory.au3 works but i can't figure out the syntax i guess...

Maybe understanding the equation will help me, is it like this?

29E99288 <target address

address of pointer.......033C2030...............................offset(hex) 278

address of pointer....ElementClient.exe+005E7C8C...offset(hex) 28

elementclient.exe+005E7C8C+28=033C2030

then

033C2030+278=29E99288

???????????????????????????????????????????????

Did you try using NomadMemory.au3 ?

And if you just want the pointers to be loaded on startup, create an .ini file, and make autoit load the values.

Link to comment
Share on other sites

Did you try using NomadMemory.au3 ?

And if you just want the pointers to be loaded on startup, create an .ini file, and make autoit load the values.

yeah i am using nomadmemory......... i have no problem reading memory... my problem is scripting autoit to calculate the pointers so i don't have to manually enter them every time

Link to comment
Share on other sites

after working with a similar script and memorygetbase myself for about a month with no success i just found the base address which has only changed in pwi once in the last 6 months with the physical base i then use offsets and build from there and like i said ive only had to change that base once. ill post and example of my ini after work. (not on home pc)

Link to comment
Share on other sites

It's funny, I was working with a mate on doing memory reading - which also includes 'hooking' (by injecting bytecode into the process), and I wrote a few functions to help with this.

(there're not in a UDF format - from what I know):

; Writing. Quite simple: Pass it a handle to the process(obtained from the _WinAPI_OpenProcess function), the address to write to, the data you wanna write, and the data type(if other than byte).
Func _WriteProcessMemory(ByRef $hvProcess, $ivAddress, $bvData, $svDataType = "byte")
    Local $stvWritten = DllStructCreate("int Written")
    Local $stvData = DllStructCreate($svDataType)
    DllStructSetData($stvData, 1, $bvData)
    Local $avResult = DllCall("Kernel32.dll", "int", "WriteProcessMemory", "int", $hvProcess, "int", $ivAddress, "ptr", DllStructGetPtr($stvData), "int", DllStructGetSize($stvData), "int", DllStructGetPtr($stvWritten))
    Return(SetError($avResult[0], 0, DllStructGetData($stvWritten, "Written")))
EndFunc

; Simplified reading of memory(never used nomad memory or any of those others so I dunno how 'user-friendly' they are). Pass it a handle of the process(obtained through _WinAPI_OpenProcess), the address to read from, and the data type(if other than byte), and it'll return the value directly.
Func _ReadProcessMemory(ByRef $hvProcess, $ivAddress, $svDataType = "byte")
    Local $stvRead = DllStructCreate("int Read")
    Local $stvData = DllStructCreate($svDataType)
    Local $avResult = DllCall("Kernel32.dll", "int", "ReadProcessMemory", "int", $hvProcess, "int", $ivAddress, "ptr", DllStructGetPtr($stvData), "int", DllStructGetSize($stvData), "ptr", DllStructGetPtr($stvRead))
    Return(SetError(Not $avResult[0], DllStructGetData($stvRead, "Read"), DllStructGetData($stvData, 1)))
EndFunc

; This, from what I can tell does the same (and more if needed) that which the MemoryGetBaseAddress function does. Just give it the process id, and the main executable module name of the game, module name, ex: "ElementClient.exe"))
Func _ProcessGetModuleBase($ivPID, $svModuleName)
    $ivPID = ProcessExists($ivPID)
    If Not $ivPID Then Return(SetError(1, 0, 0)); Process does not exist
    
    Local Const $TH32CS_SNAPMODULE = 0x00000008
    Local Const $sMODULEENTRY32Struct = "dword Size;" & _
                            "dword 32ModuleID;" & _
                            "dword 32ProcessID;" & _
                            "dword GlblcntUsage;" & _
                            "dword ProccntUsage;" & _
                            "ptr modBaseAddr;" & _
                            "dword modBaseSize;" & _
                            "hwnd hModule;" & _
                            "char Module[255];" & _
                            "char ExePath[260]"
    
    Local $hvSnapShot = DllCall("Kernel32.dll", "hwnd", "CreateToolhelp32Snapshot", "dword", $TH32CS_SNAPMODULE, "dword", $ivPID)
    If Not $hvSnapShot[0] Then Return(SetError(2, 0, 0)); Could not create snapshot?

    Local $stMODULEENTRY32 = DllStructCreate($sMODULEENTRY32Struct)
    DllStructSetData($stMODULEENTRY32, "Size", DllStructGetSize($stMODULEENTRY32))

    Local $ivState = DllCall("Kernel32.dll", "int", "Module32First", "hwnd", $hvSnapShot[0], "long_ptr", DllStructGetPtr($stMODULEENTRY32))
    If Not $ivState[0] Then Return(SetError(3, _WinAPI_CloseHandle($hvSnapShot[0]), 0)); Could not enumerate first module in list?
    Local $ivRet = 0
    Local $svModule
    
    Do
        $ivRet = DllStructGetData($stMODULEENTRY32, "modBaseAddr")
        $svModule = DllStructGetData($stMODULEENTRY32, "Module")
        If $svModule = $svModuleName Then ExitLoop
        $ivState = DllCall("Kernel32.dll", "int", "Module32Next", "hwnd", $hvSnapShot[0], "long_ptr", DllStructGetPtr($stMODULEENTRY32))
        Sleep(1)
    Until Not $ivState[0]
    
    _WinAPI_CloseHandle($hvSnapShot[0])
    
    Return $ivRet
EndFunc

; This will help in reading pointers: pass it a handle(same as with write and read funtions) to the process, the address of the base pointer, and the offset(s).
; The offset has to be passed as an array(this is due to multi-level pointers), basically, it just reads the value from the first pointer, then reads from the value it got+offset, then it does that for every offset.
; Which in the end returns the address the last offset through the pointer+offsets leads it to.
Func _ReadProcessPointers(ByRef $hvProcess, $ivBaseAddress, $avOffsets)
    If Not IsArray($avOffsets) Then Return _ReadProcessMemory($hvProcess, $ivBaseAddress, "ptr")
    $ivBaseAddress = _ReadProcessMemory($hvProcess, $ivBaseAddress, "ptr")
    
    For $i = 0 To UBound($avOffsets)-1
        $ivBaseAddress = _ReadProcessMemory($hvProcess, $ivBaseAddress+$avOffsets[$i], "ptr")
    Next
    Return $ivBaseAddress
EndFunc

Also, offsets in cheat engine, is in hex, doing Dec("12") will not return the correct value, you need to do Dec("0x12").

And preferably use Number instead of Dec, as the Dec function is supposed to convert numbers to decimal not strings, while Number converts from strings to a number(obviously), otherwise Dec will first call Number to first convert it into a number, then Dec will run(so basically you're running two instructions when you only have to run one). :idea:

I don't know if this will solve your problem or anything, but the main issue I think is that you're doing Dec("12"), instead of Number("0x12"), but why not just give it in hex value directly? :)

Edit:

Also, pointers work like this:

Base pointer = static pointer, or pointer that points to the 'correct' address all the time(correct being the address you want/need it to point to).

if you read the value that the address the base pointer is located at(as a ptr), it will give you the address to some other pointer(or directly to the address you're after),

if it's a multi-level pointer, adding/subtracting the offset to/from the value you read from the base pointer will give you the next pointer address.

So:

SecondPointer = readmemory(BasePointer+offset)

ThirdPointer = readmemory(SecondPointer+offset)

HealthAddress = ThirdPointer+offset

HealthValue = readmemory(HealthAddress)

I hope that makes sense.. :party:

Edited by FreeFry
Link to comment
Share on other sites

if you watched my first post i said that what he was doing is a dead road for what he wants. the code that i posted will help him understand a working path.its code i found in these forums that i adapted and learned from. in other words it is allready posted inthese forums thats all.

Link to comment
Share on other sites

You said you were going to post an example, not a 1000+ line script...

In my opinion that will only make him more confused, unless he really wants to spend time to understand the whole of the script. Maybe an explanation of what it does, and how it works would be in order(examples are complementary with a description you know :party:). :)

Link to comment
Share on other sites

point taken and i can agree

i know for some a working copy is good enough

i need to look under the hood to be happy

Global $APP_BASE_ADDRESS = "0x" & Hex(IniRead($SOFTWARE_OFFSET_CONFIG, $CFG_BASEADDRESS_ROOT_KEY, $CFG_BASEADDRESS_KEY, "9885820"));instead of lalala+45678 use the 0x123456 actual address

Global $PROCESS_INFORMATION = _MemoryOpen($PROCESS_ID)


Global $OFFSET_AT[3]
$OFFSET_AT[1] = 32
$OFFSET_AT[2] = IniRead($SOFTWARE_OFFSET_CONFIG, $CFG_OFFSET_ROOT_KEY, $CFG_OFFSET_AT, "2648")
Global $OFFSET_MP[3], $OFFSET_MAX_MP[3]
$OFFSET_MP[1] = 32
$OFFSET_MP[2] = IniRead($SOFTWARE_OFFSET_CONFIG, $CFG_OFFSET_ROOT_KEY, $CFG_OFFSET_MP, "1128")
$OFFSET_MAX_MP[1] = 32
$OFFSET_MAX_MP[2] = IniRead($SOFTWARE_OFFSET_CONFIG, $CFG_OFFSET_ROOT_KEY, $CFG_OFFSET_MAXMP, "1176")
Global $OFFSET_HP[3], $OFFSET_MAX_HP[3]
$OFFSET_HP[1] = 32
$OFFSET_HP[2] = IniRead($SOFTWARE_OFFSET_CONFIG, $CFG_OFFSET_ROOT_KEY, $CFG_OFFSET_HP, "1124")
$OFFSET_MAX_HP[1] = 32
$OFFSET_MAX_HP[2] = IniRead($SOFTWARE_OFFSET_CONFIG, $CFG_OFFSET_ROOT_KEY, $CFG_OFFSET_MAXHP, "1172")

$LABEL_OFFSETH_HP = GUICtrlCreateLabel("Hex: " & Hex($OFFSET_HP[2]), 80, 370, 85, 20)
Edited by Diception
Link to comment
Share on other sites

the lalala part of "lalala+45678" is part of the module allocation base, this CAN differ from system to system, so resolving lalala to an actual address is good procedure(otherwise a static address might not be static if you use a direct address, instead of an offset one).

also, reading pointers can be very easy if one use the _ReadProcessPointers helper function that i posted earlier:

Say you have a base pointer which you want to use to resolve the address of your health for example, and that this pointer is located at game.exe+1234:

We then we define a variable which contains that address(can be simplified with my _ProcessGetModuleBase function), and then use the _ReadProcessPointers function to resolve the pointer to the address we're after:

#include <WinAPI.au3>
#include <Constants.au3>

Dim $iPID = ProcessExist("game.exe"); We should store this, as we'll be using it later
Dim $iHealthBasePtr = _ProcessGetModuleBase($iPID, "game.exe")+0x1234; Find the allocation base(address) of game.exe and add the offset the pointer is at to that
Dim $aHealthPtrOffsets[2] = [0x54, 0x10]; This would be for a 3 level pointer(first pointer is the base pointer), second pointer offset = 0x54, third = 0x10

Dim $hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, 0, $iPID, 0); Get a handle to the process

Dim $iHealthAddress = _ReadProcessPointers($hProcess, $iHealthBasePtr, $aHealthPtrOffsets); This will resolve the absolute address of the Health address from the base pointer + offsets

Dim $iHealth
While 1
$iHealth = _ReadProcessMemory($hProcess, $iHealthAddress, "float"); Read the health as a float(for example, if the health where stored as a dword, just specify dword as Data-type
; Do something based on what your health is
Sleep(250)
WEnd

Func _ReadProcessPointers(ByRef $hvProcess, $ivBaseAddress, $avOffsets)
    If Not IsArray($avOffsets) Then Return _ReadProcessMemory($hvProcess, $ivBaseAddress, "ptr")
    $ivBaseAddress = _ReadProcessMemory($hvProcess, $ivBaseAddress, "ptr")
    
    For $i = 0 To UBound($avOffsets)-1
        $ivBaseAddress = _ReadProcessMemory($hvProcess, $ivBaseAddress+$avOffsets[$i], "ptr")
    Next
    Return $ivBaseAddress
EndFunc

Func _ReadProcessMemory(ByRef $hProcess, $pBaseAddress, $svDataType = "byte")
    
    Local $stRead = DllStructCreate("int Read")
    Local $stData = DllStructCreate($svDataType)
    Local $aResult = DllCall("Kernel32.dll", "int", "ReadProcessMemory", "int", $hProcess, "int", $pBaseAddress, "ptr", DllStructGetPtr($stData), "int", DllStructGetSize($stData), "ptr", DllStructGetPtr($stRead))
    
    Return(SetError(Not $aResult[0], DllStructGetData($stRead, "Read"), DllStructGetData($stData, 1)))
EndFunc

Pseudo code, not tested(the functions work though ^^) :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...