How to make my pointer point a to static address, which change with game version update, in assembly script?

Anything Cheat Engine related, bugs, suggestions, helping others, etc..
Post Reply
CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

Hello, I'm trying to make a cheat for dominions 6.
It stores a value in static address. The address will change when game version updates, so I want to make a script search for it and work for many versions hopefully.
This is what I made, the scan, enable and disable part works, but I have no idea how to set the address to the pointer DPLAddr.

Please help me.


{ Game : Dominions6.exe
Version:
Date : 2024-02-01
Author : CannonFodder

This script does blah blah blah
}

[ENABLE]

aobscanmodule(DesignPointsLimitInject,Dominions6.exe,8B 05 ? ? ? ? 41 83 FD 02 0F 44 05 ? ? ? ? 89 05 ? ? ? ? 85 DB) // should be unique
alloc(newmem,$1000,DesignPointsLimitInject)

registersymbol(DPLAddr)
label(DPLAddr)

registersymbol(code)
label(code)
label(return)

newmem:
//db 8b 05
//readmem
code:
readmem(DesignPointsLimitInject,6)
//mov eax,[Dominions6.exe+3DE45008] //address change with game version, use readmem
//How can I make my pointer DPLAddr point to the static address???????
jmp return

DPLAddr:
dd 0

DesignPointsLimitInject:
jmp newmem
nop
return:
registersymbol(DesignPointsLimitInject)

[DISABLE]

DesignPointsLimitInject:
readmem(code,6)
//db 8B 05 E2 E0 BA 3D

unregistersymbol(DPLAddr)
unregistersymbol(DesignPointsLimitInject)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: Dominions6.exe+296F20

Dominions6.exe+296EF5: 45 8B F4 - mov r14d,r12d
Dominions6.exe+296EF8: 66 89 44 24 75 - mov [rsp+75],ax
Dominions6.exe+296EFD: 88 44 24 77 - mov [rsp+77],al
Dominions6.exe+296F01: 44 89 44 24 4C - mov [rsp+4C],r8d
Dominions6.exe+296F06: 89 54 24 48 - mov [rsp+48],edx
Dominions6.exe+296F0A: 89 74 24 40 - mov [rsp+40],esi
Dominions6.exe+296F0E: 44 89 64 24 44 - mov [rsp+44],r12d
Dominions6.exe+296F13: E8 F8 76 F7 FF - call Dominions6.exe+20E610
Dominions6.exe+296F18: 44 8B AD 90 1D 00 00 - mov r13d,[rbp+00001D90]
Dominions6.exe+296F1F: 90 - nop
// ---------- INJECTING HERE ----------
Dominions6.exe+296F20: 8B 05 E2 E0 BA 3D - mov eax,[Dominions6.exe+3DE45008]
// ---------- DONE INJECTING ----------
Dominions6.exe+296F26: 41 83 FD 02 - cmp r13d,02
Dominions6.exe+296F2A: 0F 44 05 D3 E0 BA 3D - cmove eax,[Dominions6.exe+3DE45004]
Dominions6.exe+296F31: 89 05 21 EB FE 11 - mov [Dominions6.exe+12285A58],eax
Dominions6.exe+296F37: 85 DB - test ebx,ebx
Dominions6.exe+296F39: 79 22 - jns Dominions6.exe+296F5D
Dominions6.exe+296F3B: 44 89 64 24 30 - mov [rsp+30],r12d
Dominions6.exe+296F40: 45 8B CC - mov r9d,r12d
Dominions6.exe+296F43: 89 74 24 28 - mov [rsp+28],esi
Dominions6.exe+296F47: 45 33 C0 - xor r8d,r8d
Dominions6.exe+296F4A: 33 D2 - xor edx,edx
}

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

^ check out my AC Valhalla table as example:
- open up Lua startup script and find 'getStaticAddr(...' (near the bottom)
(this is the routine I made to pick up (hardcoded offset) addresses.
- principle: since i do not like using wildcards in my aobs, the function is set up in this way that you can use a signature in proximity of that location (~ less likely to break by updates), and then just add the number of bytes (+/-) to get the actual opcode location
- CE's disassemble() will take care of the rest; basically collecting the proper address itself
(you do not need to worry about any offset calculations ~ which i did in the past (greyed out stuff))
=> you'll find an example in the main script (and many of my tables use it to collect that kind of info)

tip: enable the print statements so that you'll get a better understanding of what it does where/when...

Notes:
1. you can do this type of calcution in ASM as well btw
(I have done this in the past and plenty of tables around that perform this action as well ~ do not ask, I can't remember where/when)
=> though you'll find more tables using a Lua variant here... !
2. feel free to use this function; no problems (and/or adapt to your liking)
3. if the pointer remains pretty much the same during gameplay, then just use Lua (waaaaaaaaaay easier)
4. the function allows you to collect either the (initial) ptr address (in case it changes during gameplay ~ iow the address between them [xxx]), the actual (structure) pointer (the value of that [xxx] location) or the opcode address itself...
(depending on what you want to do with that info)

TIP 2: it is not always possible to get an "convenient" opcode close to that particular pointer info. Try this:
- go to start of the module (in Memory viewer)
- select [search - asm code]
- search for that address... and it will pick up/show all opcodes accessing that particular pointer
(more likely to happen if the address in question is important)
- use an opcode that better fits your needs...

CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

Sorry for I have no knowledge of Lua, but I'll try to learn.

local addrProc = getStaticAddr(sCheckProc,0,"",3,startAddr,endAddr,sProtFlags)
function getStaticAddr(sAOB,nOffset,sBaseAddr,nEval,nStartMem,nEndMem,sFlags,bFoundList)

I found your Lua function but can't quite understand the parameters and return value.
What shall shall I pass into them?

local addrProc = getStaticAddr("Dominions6.exe",0,"",3,startAddr,endAddr,sProtFlags)
local addrProc = getStaticAddr("8B 05 ? ? ? ? 41 83 FD 02 0F 44 05 ? ? ? ? 89 05 ? ? ? ? 85 DB",0,"",3,startAddr,endAddr,sProtFlags)

And what does the return value mean?
Judge by the name, it returns the base address of a process? In my case the base address of Dominions6.exe?

AlexS
Expert Cheater
Expert Cheater
Posts: 309
Joined: Sun Apr 08, 2018 3:46 pm
Reputation: 185

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by AlexS »

CannonFodder wrote:
Thu Feb 01, 2024 2:10 am
Please help me.

(Google translation)

Use instruction bytes containing a static address.
This is the assembly code from your example. Pay attention to the highlighted areas.
Dominions6.exe+296F20: 8B 05 E2 E0 BA 3D - mov eax,[Dominions6.exe+3DE45008]
// ---------- DONE INJECTING ----------
Dominions6.exe+296F26: 41 83 FD 02 - cmp r13d,02
If you take the allocated bytes from the first instruction and add them to the allocated offset of the next instruction, you will get the offset of the address you need.
Bytes allocated: E2 E0 BA 3D = 0x3DBAE0E2
Next instruction offset: 0x296F26
Result: 0x3DBAE0E2 + 0x296F26 = 3DE45008

Let's check it using the following instructions from your example.
Dominions6.exe+296F2A: 0F 44 05 D3 E0 BA 3D - cmove eax,[Dominions6.exe+3DE45004]
Dominions6.exe+296F31: 89 05 21 EB FE 11 - mov [Dominions6.exe+12285A58],eax
Bytes allocated: D3 E0 BA 3D = 0x3DBAE0D3
Next instruction offset: 0x296F31
Result: 0x3DBAE0D3 + 0x296F31 = 3DE45004

Sorry for bad English, hope you understood my explanations.

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

first off: #AlexS is correct based on his explanation. I haven't done this for quite awhile so...

As for my function:
****
1. copy that function in the lua start up script (you can also place it in the same script as your asm script btw)
> if you place it in the lua start up, you must allow to execute... !
> if in the asm script itself, just copy the fn right below the {$lua} tag (see below)
2. add following to the 'lua section' of your asm script:
(better yet, create a new "blank" script and just copy/paste following below in there...
3. enable the script, then - via memViewer - goto 'pMyPointer' location in lower window; and it should give you your address...
4. if everything works out well, then add it to your actual script...

Note: Lua code will always be executed first, which is why your asm script can use its info thereafter !


****
[ENABLE]
{$lua}

-- initializes your ptr_var ~ "similar" to registerSymbol + alloc()
unregisterSymbol("pMyPointer")
if not getAddressSafe("pMyPointer") then registerSymbol("pMyPointer", allocateMemory(8)) end

-- assuming that following signature is unique (i'm avoiding them offset opcodes here)
local sAOB = "44 89 64 24 30 45 8B CC 89 74 24 28"

-- the actual opcode_start_byte you want sits 27 bytes above this location...
-- > I do this to avoid wildcards, but 'rsp' references are not "great" either
-- > You can obviously use your current sig; in that case use '0' as count (instead of 27)
-- > 2 = the found address will be written to "pMyPointer" (is done inside that function); basically '[Dominions6.exe+3DE45008]'
-- > 0 = 'Dominions6.exe+3DE45008' will be written to "pMyPointer" (your pick depending on how that value behaves during gameplay)
-- > (in my experience, 2 = good in 95% of the cases)

getStaticAddr(sAOB,27,"pMyPointer",2)


{$asm}
// (your asm script here)


[DISABLE]
****

notes:
a. i've done some copy/pasting but obviously no "live testing"; so it might return some syntax error
b. if fn is added to lua startup, better save/quit and then reload...
c. placing '--' in front of some code basically comments it out (similar to '//' in asm)



PS: I only started using Lua 3-5 years into tablemaking; so no surprise on my end :)

CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

I made the asm solution successfully thanks to the instruction from AlexS.
Now trying to get the lua solution done.
I put the function in the script enable part.

getStaticAddr(sAOB,0,"dplLuaAddr",0)

result:
dplLuaAddr address
1EB034C0000
value
600

getStaticAddr(sAOB,0,"dplLuaAddr",2)

result:
dplLuaAddr address
1EB034E0000
value
600

actual:
Dominions6.exe+3DE45008
address
7FF66FD25008
value
600

It seems the function reads the value from [Dominions6.exe+3DE45008] instead of the address of Dominions6.exe+3DE45008?
What's wrong?

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

^ upload table with script you've made and pm link or add to above post; and I'll have a look.
+: get me prtscrn of the memViewer with a) the opcode showing b) the 'edit opcode' window showing the actual ptr value
(mov eax,[???]') ?
=> depending on the option taken, you'll have to:
> 2: just add an entry_ptr referencing 'dplLuaAddr'
> 0: add an additional 0+offset line

CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

viewtopic.php?f=2&t=27375&p=332826#p332826

this is the table I made
the lua option fail to work is Get Design Points Limit LUA (WIP)
the entry is hidden under the script group

the actual static address is:
Dominions6.exe+296F20 - mov eax,[Dominions6.exe+3DE45008]
mov eax,[7FF66FD25008]

7FF66FD25008

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

^ if you want the address between brackets [] (= 7FF66FD25008) then you select option '0'... which should return that address (but you've seem to have tried that already based on your feedback earlier ?!).

some more info on the function:
* createMemScan(false) == aobscan using GUI (all them properties you can set there can be defined here as well ~ eg start/end mem_address)
> i'm doing a 'scan.getOnlyResult()', which practically means it will take the 1st result it finds... which will be placed in 'addrStruct'
(if you remove the '--' in front of the print_statement right before the 'if' then it'll show you that - in this case - opcode address)
=> disassemble(addrStruct): basically does precisely the same as you double-clicking that opcode; and returns it as a string
(see your post above, being 'mov eax,[7FF66FD25008]')
=> the 'match' method will get the info between them brackets '[7FFxxxxx]'; which - being string - needs to be converted to a number
=> just below: if you selected '2', it will get the pointer_value (being [7FF66FD25008]) (if '0', it should return '7FF66FD25008')
('3' i consider a special case)
=> and finally it writes that (ptr) value to the defined symboladdress...

ps: I did a quick search on that game (it is about 300 MB, right ?); seems a repack can be grabbed somewhere. when back home, I'll try to get my hands on one. If you could upload a save and pm link, would be swell...

CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

yes, it's about 350mb
I downloaded version 6.03 from some repack site too.
The save file is unnecessary, the address stores god design points limit, which is accessed when you create a new game.
I myself is on turn 2 right now.

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

^ a picture replaces a 1000 words (or so) 8-) : [ [Link] ]
anywho: you did everything correct. the only thing I did in this particular situation is opting for '0'; which gets you that '7FFxxx' address. I think you got confused with the mem_address allocated to the registerSymbol here ?!

And I tend to use the "pointer syntax": if that 7FF... address somehow gets erased/changed/become_invalid (or the symbol itself for that matter), CE will usually detect this and show '??'. Which is important for values that are locked by the user: CE will try to write to that memory if still "valid", which can cause crashes if that memory has been used again for some other data(structure)...

ps: if something is still unclear in that pic, do ask...

CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

Thank you for you help!
I did tried to change to pointer, but it was when I use getStaticAddr(sAOB,0,"dplLuaAddr",2), thus I didn't get the right address and got confused before.

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

^ glad i could help.

To recap (if you plan to use this function more)
a. 2 = get pointer (to some struct ~ most cases)
b. 0 = get address of some system_info (typical: FOV, daytime, console_vars, etc)
c. 3 = get opcode location itself (which is returned ~ local addrOpcode = getStaticAddr() - rather exceptional: e.g.stack_return verification)
d. nStartMem,nEndMem = when aobscan is really slow you can speed up search by limiting its memory_range
(just like you can do via the GUI - typical situation: a "preloader" game_exe with actual gamecode in DLL)
e. sFlags = when aobscan needs different protection flags to return results (typical: you have to set 'Writable' enabled)
f. bFoundList = only used this once/twice: the lua variant did not return a result while the gui did.
(upon checking the 'foundlist' it did have that address ~ surely I needed to set some of the other params properly ?!)


For completeness sake: (see #AlexS above)
in x32 games, you do not need to perform any calculations on that (4-byte) hexvalue (asm--wise) as it returns you the actual address you want. (i should test/verify this though :oops:)

And finally, something I always do for this type of info: [ [Link] ] (I normally let it run for about 5 mins)
(it will/can allow you to choose for a "better" opcode location, less prune to fail by updates)
=> if you get "plenty" of results returned, then that is usually a good indication about the value's importance...
Last edited by Paul44 on Sat Feb 03, 2024 4:53 pm, edited 1 time in total.

CannonFodder
Table Makers
Table Makers
Posts: 188
Joined: Mon May 08, 2017 3:34 pm
Reputation: 108

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by CannonFodder »

What's the scan feature you used in your pic? I can't find it.
dominions 6 is x64 program, I think your function returned the correct 8 bytes address of 7FF66FD25008?
Do you mean if the offset of Dominions6.exe+3DE45008 is larger than 4 bytes, like Dominions6.exe+112233443DE45008, your function may return wrong address?

Paul44
Table Makers
Table Makers
Posts: 760
Joined: Thu Jul 27, 2017 9:02 am
Reputation: 444

Re: How to make my pointer point a to static address, which change with game version update, in assembly script?

Post by Paul44 »

I've updated the pic in my prev post. How to proceed:
1. goto start of game_exe/module: I always goto '$process', using right-click option (unless you need to work in a DLL)
2. then select that search option, just fill in that address - between [ ] here - in the new window
3. when the search starts, it'll show you that progress window...

as for you Q: no. check the function again: i'm not doing ANY calculations there (I used to do that ~ the greyed part, which basically did what #AlexS explained earlier), as the 'disassemble()' takes care of that. Just make sure you always get the location of the 1st byte of your opcode instruction, so it'll disassemble them bytes correctly...

Post Reply

Who is online

Users browsing this forum: No registered users