Read memory and offsets Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Read memory and offsets

14 Feb 2018, 15:48

Hello i used cheat engine to scan for pointers and got the following:
Image
From what i understand this means:

Code: Select all

BaseOffset := 0x00B8C83C
offset0 := 0x0
offset1 := 0xA8
offset2 := 0x3FC
The first thing i don't understand is:
If those values are always the same then what changes the result? I think that it's the BaseAddress that i still don't know how to find (yes used google but can't find something that i understand)

Then if the BaseAddress changes how do i get that address everytime i launch the exe?

Also tried the following (obtained this while searching on the forum before posting)

Code: Select all

winget, pid, PID, asd
global ProcessHandle:= DllCall("OpenProcess","Int",16,"Int",0,"UInt",pid)
ReadMemory(MADDRESS)
{
	VarSetCapacity(MVALUE,4,0)
	DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
	return *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
}


f1::
;//Read from current Dynamic address
addr := 0x03D6F8FC    
DynAddr := ReadMemory(addr)

;//Read from Static Pointer
addr0 := 0x00B8C83C
offset0 := 0x0
offset1 := 0xA8
offset2 := 0x3FC

value0 := ReadMemory(addr0)
addr1 := value0 + offset0
msgbox %value0% and %addr1%

value1 := ReadMemory(addr1)
addr2 := value1 + offset1
msgbox %value1% and %addr2%

value2 := ReadMemory(addr2)
addr3 := value2 + offset2
msgbox %value2% and %addr3%

StaticAddr := ReadMemory(addr3)
msgbox %staticaddr%

MsgBox, Dynamic Address,`n Player = %DynAddr%  `n`nStatic Pointer,`n Player = %StaticAddr% `n
return
Result i get: Image

Thank you for your time.

@edit:
Okay i found this and it worked BUT i still have a question about this:

Code: Select all

GetImageBase(filename)
{
    static IMAGE_DOS_SIGNATURE := 0x5A4D
    static IMAGE_NT_SIGNATURE := 0x4550
    static IMAGE_SIZEOF_FILE_HEADER := 20
    static MAGIC_PE32 := 0x10B
    static MAGIC_PE32PLUS := 0x20B

    file := FileOpen(filename, "r")
    if !file
        return
    
    if (file.ReadUShort() != IMAGE_DOS_SIGNATURE)
    || !file.Seek(60) ; Seek to e_lfanew.
    || !file.Seek(file.ReadInt()) ; Seek to NT header.
    || (file.ReadUInt() != IMAGE_NT_SIGNATURE)
        return
    
    file.Seek(IMAGE_SIZEOF_FILE_HEADER, 1) ; Seek to optional header.
    
    magic := file.ReadUShort()
    if (magic = MAGIC_PE32)
    {
        file.Seek(26, 1)
        return file.ReadUInt()
    }
    else if (magic = MAGIC_PE32PLUS) ; x64
    {
        file.Seek(22, 1)
        return file.ReadInt64()
    }
}
I tried reading and searching each line but i don't understand what is this for. As Lexikos said in the same post i obtained this code from:
EXE files typically have a fixed base, determined when the file is compiled. You can read it from the file's header
Does this means that if i share my exe then this base address won't change?. Then i don't have to check this address everytime unless exe changes?

Again thank you for your time
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

Re: Read memory and offsets  Topic is solved

14 Feb 2018, 22:21

I tried reading and searching each line but i don't understand what is this for.
Programs will either have a dynamic (ASLR) base address which changes every time it is run, or they will have a static base address which never changes.

In the case of the static base address, this address is set when the program is compiled/created - a value is written into the exe which specifies the base address, it is typically 0x400000. Lexikos' function will find and read this value from the exe.

With regards to reading memory of a program which has a static base address, there is no real point in using the above function, as the base address never changes - instead you can hard code this value (usually 0x400000) into your script. There are a number of ways to find this base address in CE, but the simplest is to add the process name as an address in CE, the example below shows that the game FTLGAME.exe has a base address of 0x00A90000.

Image

To determine if a process uses a dynamic or static base address, simply add the process name as an address just like above and restart the program - if the base address is the same after restarting, then it is a static address. It sounds like your program has a static base address.

If a program has a dynamic base address, then Lexikos' function will not work, as the address is not hard coded into the executable. Instead you will have to use another function - see the code provided below.
Does this means that if i share my exe then this base address won't change?. Then i don't have to check this address everytime unless exe changes?
Correct.

If you ever need to find a dynamic base address, read memory values other than UInts, or wish to read pointers in a single line, then this memory class can help.
https://github.com/Kalamity/classMemory


Here is an example used to read your pointer - you would need to change the "FTLGAME.exe" to match your EXEs name.

Code: Select all

; The contents of this file can be copied directly into your script. Alternately, you can copy the classMemory.ahk file into your library folder,
; in which case you will need to use the #include directive in your script i.e. 
#Include <classMemory>

; You can use this code to check if you have installed the class correctly.
if (_ClassMemory.__Class != "_ClassMemory")
{
    msgbox class memory not correctly installed. Or the (global class) variable "_ClassMemory" has been overwritten
    ExitApp
}


f1::

; Open a process with sufficient access to read and write memory addresses (this is required before you can use the other functions)
; You only need to do this once. But if the process closes/restarts, then you will need to perform this step again.
; .isHandleValid() can be used to check if program has restarted.
; Note: The program identifier can be any AHK windowTitle i.e.ahk_exe, ahk_class, ahk_pid, or simply the window title. 
; Unlike AHK this defaults to an exact match, but this can be changed via the passed parameter.
; hProcessCopy is an optional variable in which the opened handled is stored. 


; *****  change FTLGAME.exe to your process name ******
mem := new _ClassMemory("ahk_exe FTLGAME.exe", "", hProcessCopy) ; *****

; Check if the above method was successful.
if !isObject(mem) 
{
    msgbox failed to open a handle
    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. Consult A_LastError for more information.
    ExitApp
}

; read a pointer - mem.BaseAddress is automatically set to the base address.
value := mem.read(mem.BaseAddress + 0x00B8C83C, "UInt", 0x0, 0xA8, 0x3FC)

msgbox val = %value%

return
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Read memory and offsets

14 Feb 2018, 22:55

Wow didn't expect an aswer like that. Thank you for the time you took to write that.
You helped a lot now i understand what i'm doing with that code haha. Thank you!!
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Read memory and offsets

14 Feb 2018, 23:59

RHCP wrote:If you ever need to find a dynamic base address, read memory values other than UInts, or wish to read pointers in a single line, then this memory class can help.
https://github.com/Kalamity/classMemory
Mainly as just a shoutout and thank you to RHCP, I also use classMemory and highly recommend it.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Mannaia666, wpulford and 419 guests