Jump to content

Memory UDF


Szhlopp
 Share

Recommended Posts

For all the people who use NomadMemory.

In CheatEngine, a 'static' address looks like "Solitaire.exe+753EC" right?

In AutoIt this was useless, until now....

_MemoryGetBaseAddress($ah_Handle, $iHexDec)

This function will find what "Name.exe" equals. All it requires is the values returned by _MemoryOpen() :D

Below is the UDF combined with example usage.

#include <NomadMemory.au3>
#include <GUIConstants.au3>
SetPrivilege("SeDebugPrivilege", 1)


If WinExists("InkBall") = 0 Then
    MsgBox(0, "", "Application is not running. Please run it before starting this app.")
    Exit
EndIf


Global $Offset1[3]
$Offset1[0] = 0 ; Is ALWAYS 0.
$Offset1[1] = Dec("26BC") ; Static Addr Oset.
$Offset1[2] = Dec("24")
Global $Offset2[3]
$Offset2[0] = 0 ; Is ALWAYS 0.
$Offset2[1] = Dec("26B8") ; Static Addr Oset.
$Offset2[2] = Dec("24")
Global $TimeAddress, $BlocksAddress
Global $FreezeTime_Time = 0
$StaticOffset = Dec("B05FC") ; "Inkball.exe+B05FC" - CheatEngine formatted static address.
$pid = ProcessExists("InkBall.exe")



$GUI = GUICreate("InkBall Hacker", 216, 181, 193, 125)
$Time = GUICtrlCreateInput("", 20, 40, 185, 21)
$TimeLabel = GUICtrlCreateLabel("Time (milliseconds):", 20, 18, 200, 17)
$Blocks = GUICtrlCreateInput("", 20, 102, 185, 21)
$BlocksLabel = GUICtrlCreateLabel("Blocks:", 20, 80, 200, 17)
$SetButton = GUICtrlCreateButton("Set", 72, 135, 72, 30, 0)
$TimeFreeze = GUICtrlCreateCheckbox("Freeze", 150, 65)
GUISetState(@SW_SHOW)



$openmem = _MemoryOpen($pid) ; Open the memory
$baseADDR = _MemoryGetBaseAddress($openmem, 1) ; "Inkball.exe+B05FC" - Gets what "Inkball.exe" equals.
$finalADDR = "0x" & Hex($baseADDR + $StaticOffset) ; Creates the final static address you read from.
AdlibEnable("UpdateValues", 400) ; Updates the values in my GUI every 4/10ths of a second.
While 1
    Sleep(20) ; Less CPU load
    
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            _MemoryClose($openmem)
            Exit
            
        Case $SetButton
            _MemoryWrite($TimeAddress, $openmem, GUICtrlRead($Time))
            _MemoryWrite($BlocksAddress, $openmem, GUICtrlRead($Blocks))
            
        Case $TimeFreeze
            
            If BitAnd(GUICtrlRead($TimeFreeze),$GUI_CHECKED) = $GUI_CHECKED Then 
                $FreezeTime_Time = GUICtrlRead($Time)
            EndIf
            
    EndSwitch
WEnd

Func UpdateValues()
    
    If WinActive($GUI) = 0 Then
        $Value = _MemoryPointerRead($finalADDR, $openmem, $Offset1)
        $TimeAddress = $Value[0]
        GUICtrlSetData($TimeLabel, "Time (milliseconds): " & $Value[1])
        GUICtrlSetData($Time, $Value[1])
        $Value = _MemoryPointerRead($finalADDR, $openmem, $Offset2)
        $BlocksAddress = $Value[0]
        GUICtrlSetData($BlocksLabel, "Blocks: " & $Value[1])
        GUICtrlSetData($Blocks, $Value[1])
    EndIf
    
    If BitAnd(GUICtrlRead($TimeFreeze),$GUI_CHECKED) = $GUI_CHECKED Then
        _MemoryWrite($TimeAddress, $openmem, $FreezeTime_Time)
    EndIf
    

EndFunc







;===================================================================================================
; Function........:  _MemoryGetBaseAddress($ah_Handle, $iHD)
;
; Description.....:  Reads the 'Allocation Base' from the open process.
;
; Parameter(s)....:  $ah_Handle - An array containing the Dll handle and the handle of the open
;                                 process as returned by _MemoryOpen().
;                    $iHD - Return type:
;                       |0 = Hex (Default)
;                       |1 = Dec
;
; Requirement(s)..:  A valid process ID.
;
; Return Value(s).:  On Success - Returns the 'allocation Base' address and sets @Error to 0.
;                    On Failure - Returns 0 and sets @Error to:
;                       |1 = Invalid $ah_Handle.
;                       |2 = Failed to find correct allocation address.
;                       |3 = Failed to read from the specified process.
;
; Author(s).......:  Nomad. Szhlopp.
; URL.............:  http://www.autoitscript.com/forum/index.php?showtopic=78834
; Note(s).........:  Go to Www.CheatEngine.org for the latest version of CheatEngine.
;===================================================================================================
Func _MemoryGetBaseAddress($ah_Handle, $iHexDec = 0)
    
    Local $iv_Address = 0x00100000
    Local $v_Buffer = DllStructCreate('dword;dword;dword;dword;dword;dword;dword')
    Local $vData
    Local $vType
    
    If Not IsArray($ah_Handle) Then
        SetError(1)
        Return 0
    EndIf
    

    DllCall($ah_Handle[0], 'int', 'VirtualQueryEx', 'int', $ah_Handle[1], 'int', $iv_Address, 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer))
    
    If Not @Error Then
        
        $vData = Hex(DllStructGetData($v_Buffer, 2))
        $vType = Hex(DllStructGetData($v_Buffer, 3))
        
        While $vType <> "00000080"
            DllCall($ah_Handle[0], 'int', 'VirtualQueryEx', 'int', $ah_Handle[1], 'int', $iv_Address, 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer))
            $vData = Hex(DllStructGetData($v_Buffer, 2))
            $vType = Hex(DllStructGetData($v_Buffer, 3))
            If Hex($iv_Address) = "01000000" Then ExitLoop
            $iv_Address += 65536
            
        WEnd

        If $vType = "00000080" Then
            SetError(0)
            If $iHexDec = 1 Then
                Return Dec($vData)
            Else
                Return $vData
            EndIf
            
        Else
            SetError(2)
            Return 0
        EndIf
        
    Else
        SetError(3)
        Return 0
    EndIf
    
EndFunc   ;==>_MemoryGetBaseAddressoÝ÷ ÚæÈ*.Á©íا¦º)zµú+«Vüç±jje{öÿ¹«miÈfz{

This will now enable AutoIt users to create their own "Trainers" or game hacks within an AutoIt script.

Once you have the address from CE you will NEVER have to get that address again.

Thanks,

Szhlopp

EDIT: To clarify what this does. ;)

Q: Golbez

I don't get what this does.

How would I need this in my script?

-----------------------------------------------------------------------------------------------------------------------------------

A:

You found the green address for whatever you were trying to get out of your game right?

To make that static address truely static you need to add It's EXE name before the address in the pointer list.

The best way to do this is to right click on the pointer stack in your 'Cheat Table' and click "Copy", then "Paste".

Now double click the address field of your copied address. You'll see the first address looks like this: "Gamename.exe+HEXOFFSET"

This is what a static address is, Game+offset.

Now in AutoIt, what does the game name equal? Obviously if I want to program the memory in AutoIt I need to know what that equals. My function tells you what that address is. Knowing that last bit of knowledge enables you to have a consistant address you use. You never need to refer back to CheatEngine to get a new address ;)

MemoryGetBaseAddressUDF.au3

Edited by Szhlopp
Link to comment
Share on other sites

  • Replies 49
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

How did you find the statics address's offset with cheat engine

If you know how to get the green address. Just copy/paste the pointer table. It will create the address offset for you.

Read the first Q/A in my original post. It says how to do it again there ;)

If you don't know how to get the 'green' address, check these out:

Tutorials

Multi-level pointers

If you have any more questions about it feel free to ask.

I got no use for this as of yet, but awesome job.

Thank you. :D

Link to comment
Share on other sites

This is brilliant.

I think more people will find an excuse to use it, if they need to get an address of a dll loaded into a process memory, i know i do!

For example, if your looking to change something at a certain address of a dll, which gets loaded by another process, that address will always change, since it doesnt get loaded the exact same time or place right? the offset remains the same but the address doesnt.

For example Game.exe may load a dll called MyDll. The address you want to change might be MyDll.dll+20C1.

Now using cheat engine you can just go to the address MyDll.+20C1 and it will take you to the correct address, but when writing an autoit script, you want to rely on cheat engine as little as possible dont you.

So previously, we would need to use GetModualHandle and EnumProcesses, one of which isnt included in autoit, and i personally didnt fancy writing it haha.

But using this method, i can now always find the base address of MyDll.dll and just add the offset to it afterwards ;)

Link to comment
Share on other sites

I wrote this a few years ago to help explain how to find offsets for games. The principle works across the board (can find offsets for any piece of software as long as you know how), and there are some new techniques I've learned... as well as learning how dumb some of my explanations sounded.

I'll update this for cheat engine and AutoIt specifically, especially since cheat engine has some nice, easy new features that makes this guide kind of obsolete. However, it's good to know what's going on under the hood, as it were.

The 10 step anti-DMA program

1.) Find the address of your variable (PtrAdd).

2.)Open the dissasembler tab in T-Search or CheatEngine. Input PtrAdd into the dissassemble box.

3.)Click the disassemble button.

4.)Change the value you are searching for, in game. You end up with some ASM code appearing. Search for something that looks like

Code:

eax +[4D]

"+4D" is your Offset, mark it down somewhere.

If eax -[4D] is what you find, change Subtract in step 5.) to Add.

5.) Subtract 4D, your offset, from PtrAdd. Convert the result to decimal. Search for the decimal number in 4Byte mode.

6.)You'll usually find a boatload of them. This is where things get a tad tedious. Filter the results with a Has/Has Not Changed routine. Once you filter 3 times with no change in the number of results, save all the results to a .cht file.

7.)Quit and reload the game, then repeat steps 1 & 5.

8.) Filter the results with a Has/Has Not Changed routine. Once you filter 3 times with no change in the number of results, load your saved .cht file and compare the results you have to the results you just found. Look for two identical addresses. Sometimes there are several, its ok. Just pick one you like.

9.) Mark down the address you found (PtrOrigin). Now, to find your variable (stored at PtrAdd,) just find the PtrOrigin, convert the value stored there to hex, Add 4D, and you have PtrAdd, where your variable is stored! Subtract 4D if your offset was -4D.

Until patchday, you can use the PtrOrigin and Offsets any way you like!

10.)Every time the .exe gamefile changes, you will need to repeat the above steps to find your offsets, PtrOrigin, & PtrAdd.

Why you just did what you did:

When Dynamic Memory Allocation (DMA) is used, the program generates and assigns a random address for certain variables to be stored at. An offset is a value which the program uses to keep structures consistent. The offset is added to the random address, then the program accesses the variable stored. The PtrOrigin is where the random address is stored. Add (or subtract!) an offset to the random address, and you end up with the PtrAdd to your variable.

Generally, you will find different data structures using the same PtrOrigin. Health, Mana, Fatigue.... Player related variables might very well all have the same PtrOrigin. Sometimes, once you find the PtrOrigin for Health, you can save yourself work by just finding the offsets for Mana, Fatigue, Gold, and XP. They do this to save CPU usage... if each variable had to use DMA individually... ugh, performance hell. Fortunately for us gamehackers, we have...

Structs, or offset footprints.

An offset footprint is oftentimes called a "struct." If you find a series of variables all related to eachother (using the same PtrOrigin), such as player data, mark down the differences (distance in hex) between each offset. If there is a difference of 1C between each variable, you can safely bet that when you have to update the offsets again, the structure will remain the same, with a difference of 1C between each PtrAdd. This allows you to easily find all the variables in the struct without reworking the Offset and PtrAdd again.

Example struct:

This isn't real. Dont use for any real games.

Code:

[base] (PtrAdd - HP Offset)

[+1A]HP

[+1A]Mana

[+1A]Stamina

[+1A]Gold

[+1A]Exp

[+1A]TargetHP

[+1A]TargetMana

[+1A]TargetStamina

Using that struct, you could simply find the PtrOrigin, go to that address, add 1A, and you have HP. Add 1A again, and you have Mana, again, Stamina, so on and so forth.

Practice finding simple variables, like health and mana. Do it 10-12 times before you move on to anything more complicated... the familiarity with anti-DMA measures will be invaluable. Sometimes there can be a PtrOrigin leading to another PtrOrigin, and dynamic offsets based on those values. If you know the basics, it becomes tedious, rather than impossible, to find the offsets and structs you're looking for.

FOR MORE DETAIL

You enter the address at which you found your variable.

If you were searching for HP and it was at 123ABC, then you'd put 123ABC into the input field.

Then, you'd change HP somehow in game. That calls the function that updates HP on your client.

That function says "Hey, wheres the pointer to the pointer for player information? OK! I see it, it's at AAA111!

Now I'll take the value at AAA111, convert to Hex (lets say it's 123000), then go to that address. Alright! Now I'm at the player information struct... hrm, what's the offset for HP?

Ahh, I see, it's ABC. I'll add ABC to the hex value of the address that signifies the beginning of the player struct. 123ABC! That means HP!"

Basically the eax/epx asm functions are designed to tell the compiler that the value being accessed is indexed. The index number is what we call offsets.

I'm a little rusty atm on proper syntax, so forgive or correct my errors; I'm just trying to help Smile

The point of doing this is to find both the index number for the variable you're searching for, and the location of where that index is stored. Imagine player information struct (or any struct) as a library.

The pointer to the pointer that indicates the beginning of the player info struct is like the library address. The index number, or offset, is like the book number.

You have to find the library first, then use the book number. The "book" number takes you to the address at which the "book", or your variable, is stored.

Hope that helped more than it confused!

Link to comment
Share on other sites

This is brilliant.

I think more people will find an excuse to use it, if they need to get an address of a dll loaded into a process memory, i know i do!

For example, if your looking to change something at a certain address of a dll, which gets loaded by another process, that address will always change, since it doesnt get loaded the exact same time or place right? the offset remains the same but the address doesnt.

For example Game.exe may load a dll called MyDll. The address you want to change might be MyDll.dll+20C1.

Now using cheat engine you can just go to the address MyDll.+20C1 and it will take you to the correct address, but when writing an autoit script, you want to rely on cheat engine as little as possible dont you.

So previously, we would need to use GetModualHandle and EnumProcesses, one of which isnt included in autoit, and i personally didnt fancy writing it haha.

But using this method, i can now always find the base address of MyDll.dll and just add the offset to it afterwards :D

Without you I never would have gotten this far. You're the one that answered my lame questions as to how the memory stuff works ;)

I wrote this a few years ago to help explain how to find offsets for games. The principle works across the board (can find offsets for any piece of software as long as you know how), and there are some new techniques I've learned... as well as learning how dumb some of my explanations sounded.

I'll update this for cheat engine and AutoIt specifically, especially since cheat engine has some nice, easy new features that makes this guide kind of obsolete. However, it's good to know what's going on under the hood, as it were.

The only reason CheatEngine is needed now is to grab the initial offsets ;)

I have a game that doesn't appear to have a pointer. I can scan what writes/reads/accesses and all that comes up is itself with ZERO offset. I'll have to try your method of getting this =)

Link to comment
Share on other sites

hehe, correct me if im wrong, but i think Notepad.exe doesnt have pointers either.

EDIT: suggestion to your code,

change $pid = WinGetProcess("Spider Solitaire")

to

$pid = ProcessExists("Spider.exe")

I think its better universally if you get the pid based on process name rather than window, not everything may have a window name ;)

Edited by SXGuy
Link to comment
Share on other sites

hehe, correct me if im wrong, but i think Notepad.exe doesnt have pointers either.

EDIT: suggestion to your code,

change $pid = WinGetProcess("Spider Solitaire")

to

$pid = ProcessExists("Spider.exe")

I think its better universally if you get the pid based on process name rather than window, not everything may have a window name ;)

Heh notepad probably doesn't :D

This is what I meant:

1) I found an address which gave me the number of lives (Not 'static').

2) I searched "Find out what writes to this address".

3) 1 address was returned, and that address was as an exact clone of the original address.

I repeated 2-3 with all the "Reads/writes/accesses" you can scan for. The only thing that came back was my original address with ZERO offset.

I updated the example and OP. Now has "$pid = ProcessExists("name.exe")".

Calltip code.

UDF formatted.

Link to comment
Share on other sites

  • 4 weeks later...

Szhlopp,

You mention game.exe+HEXADDR, but in my Cheat Engine, it prefixes the EXE like this:

000004DC_game.exe

Is that the address I'm looking for?

Thats because in CheatEngine the gamename looks like this: PID_GAME+OSET

That 000004DC is the hex value of the games PID=)

But to answer your question the _"Game" is what this finds. Which is really just the EXE's allocation base.

Answer your question?

Edit: Look at this

You found the green address for whatever you were trying to get out of your game right?

To make that static address truely static you need to add It's EXE name before the address in the pointer list.

The best way to do this is to right click on the pointer stack in your 'Cheat Table' and click "Copy", then "Paste".

Now double click the address field of your copied address. You'll see the first address looks like this: "Gamename.exe+HEXOFFSET"

This is what a static address is, Game+offset.

Now in AutoIt, what does the game name equal? Obviously if I want to program the memory in AutoIt I need to know what that equals. My function tells you what that address is. Knowing that last bit of knowledge enables you to have a consistant address you use. You never need to refer back to CheatEngine to get a new address

Edited by Szhlopp
Link to comment
Share on other sites

hey Szhlopp...I could do with some assistence on this one.....

All im tring to do is read an address and the display it

Atm im using this to veiw the value of a static address in cs:s

#include <NomadMemory.au3>
#include <GUIConstants.au3>
#include <GUIListBox.au3>
#include <Misc.au3>
#include <Array.au3>
HotKeySet("{F2}","_exit");exit
$ID=_MemoryOpen(ProcessExists("hl2.exe"))
$Address=0x243bd0c1
$team=_MemoryRead($Address,$ID)


Func _exit()
    Exit
EndFunc

  sleep(1000)
MsgBox(0,"Value", $team)

which returns my value..

now say i want to find the value of "NOTEPAD.EXE+1B6C"

how do I use MemoryGetBaseAddressUDF.au3 in the above to return the value?? I cant get my head round it....

thanks

Link to comment
Share on other sites

hey Szhlopp...I could do with some assistence on this one.....

All im tring to do is read an address and the display it

Atm im using this to veiw the value of a static address in cs:s

#include <NomadMemory.au3>
#include <GUIConstants.au3>
#include <GUIListBox.au3>
#include <Misc.au3>
#include <Array.au3>
HotKeySet("{F2}","_exit");exit
$ID=_MemoryOpen(ProcessExists("hl2.exe"))
$Address=0x243bd0c1
$team=_MemoryRead($Address,$ID)


Func _exit()
    Exit
EndFunc

  sleep(1000)
MsgBox(0,"Value", $team)

which returns my value..

now say i want to find the value of "NOTEPAD.EXE+1B6C"

how do I use MemoryGetBaseAddressUDF.au3 in the above to return the value?? I cant get my head round it....

thanks

Hey blue,

Alright let me try to explain using notepad=)

At the top I have "00000C0C_Notepad.exe"(Process is opened)

Now I magically found my green address(The 'static' address).

(Enter 5 and hit search for notepad. You'll get a green to come up)

Double click that green address so it adds it to your CheatTable. In this case the address in my table is:

0088AC48

In my CheatTable where I have the address stored I'm going to right-click the address and click copy/paste.

You can now double-click the address field and you'll see the address is now static formatted:

"notepad.exe+AC48"

In this specific case the moment you copy the address to your CheatTable it formats it. That's because it's not a pointer...

Above is how you format the address. Below I'll show you how to use it in AutoIt.

So now I know that my offset is "AC48" and my base address is obviously "Notepad.exe". I'm just going to do what CheatEngine says and just add them together like so:

$NotePadOffset = Dec("AC48") ; Here is our AC48 in decimal form


$openmem = _MemoryOpen($pid) ;Open the process

$baseADDR = _MemoryGetBaseAddress($openmem, 1) ; This grabs the "Notepad.exe"

$NotepadFinalStatic = "0x" & Hex($baseADDR + $NotePadOffset) ; Adds "Notepad.exe+AC48", changes it to Hex and add's "0x".
;Our final static address is now truely 'static'. Because you have the offset it uses and the ability to find out
; what the .exe equals. I can now _MemoryRead or use any other 'memory' functions I want on this address.
Link to comment
Share on other sites

Thanks I got it to work with and exe but not with a dll

this is what im using to scan the address

engine.dll+63D57

which should be

20063D57

#include <MemoryGetBaseAddressUDF.au3>
#include <NomadMemory.au3>
#include <GUIConstants.au3>
#include <GUIListBox.au3>
#include <Misc.au3>
#include <Array.au3>
HotKeySet("{F2}","_exit")
$ID=_MemoryOpen(ProcessExists("hl2.exe"))
$pid = ProcessExists("hl2.exe")
$HL2Offset = Dec("63D57") 
$openmem = _MemoryOpen($pid) 
$baseADDR = _MemoryGetBaseAddress($openmem, 1) 
$HL2FinalStatic = "0x" & Hex($baseADDR + $HL2Offset) 
$value=_MemoryRead($HL2FinalStatic,$ID)

If ProcessExists("hl2.exe") Then
    MsgBox(0, "Whats Happening??", "hl2 is running.")
EndIf
  sleep(1000)
MsgBox(0,"And heres its Address!", $HL2FinalStatic)


  sleep(1000)
MsgBox(0,"And heres its value!", $value)

Func _exit()
    Exit
EndFunc

I tried it with "engine.dll" instaed of "hl2" but keep getting an address returned of

00463D57

why??

regards bluerein

Edited by bluerein
Link to comment
Share on other sites

STill struggling with doing a dll instaed of an exe....

This is how I do an exe

#include <NomadMemory.au3>
 #include <GUIConstants.au3>
 #include <GUIListBox.au3>
 #include <Misc.au3>
 #include <Array.au3>
 #include <MemoryGetBaseAddress.au3>
 HotKeySet("{F2}","poke")
 
 
 
 Func poke()
 $ID=_MemoryOpen(ProcessExists("notepad.exe"))
 $pid = ProcessExists("notepad.exe")
 $Offset = Dec("7159")
 $openmem = _MemoryOpen($pid)
 $baseADDR = _MemoryGetBaseAddress($openmem, 1)
 $FinalStatic = "0x" & Hex($baseADDR + $Offset)
 _MemoryWrite($FinalStatic, $ID, 100000)
 _MemoryClose($ID)
 EndFunc 
 
 While 1
     sleep(1000)
     WEnd

How is a dll done as its not the same as an exe??

Edited by bluerein
Link to comment
Share on other sites

Sorry Bluerein, didn't notice you edited that last one :)

As far as a DLL goes I'm pretty much clueless. I've never messed DLL's in CheatEngine. Let me try though...

You have an offset of: 63D57

And you're returning: 00463D57 ?

This means our 'Base ADDR' is 00400000. I actually have been working alot on memory and there are a few strange apps where you need to start scanning for the base address at a higher position. I'll upload the modified script in the next few days but you can play with it by just changing these 2 lines:

Change this to like '0x05000000':

Local $iv_Address = 0x00100000

And this to '90000000':

If Hex($iv_Address) = "01000000" Then ExitLoop

Let me know if this works for ya,

Szh

Link to comment
Share on other sites

How do you find the base address of a address that isn't static?

Heh you need a 'static' address first. All this does is find an allocation area that has a EXE/read/write flag on it.

Also an FYI... I'm currently writing a CE/AU3 tutorial. Should show people how to use CheatEngine, AutoIT with CheatEngine, Pointers, Programming Addresses and a few tricks to finding hard pointers. :)

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...