|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
HenryEx Advanced Cheater Reputation: 1
Joined: 18 Dec 2011 Posts: 79
|
Posted: Fri Sep 13, 2024 10:03 am Post subject: Find static pointers via AOB search in executable code |
|
|
getPointerFromCodeAOB( ins_offset, aobList, OPTIONAL aobNames, OPTIONAL aob_offset, OPTIONAL isSilent, OPTIONAL registerSymbol, OPTIONAL modulename )
This LUA function will fetch you the address to a static pointer from an AOB search for code that reads from it.
You can pass it a string of bytes to AOB search, or you can pass it a whole table of multiple AOB strings to search for. You can optionally provide a table of names for the pointers, for example to automatically register a symbol for each address found. This way, you don't need to tediously update all base pointers for your table by hand when an update changes those; you only need to check the AOB searches once.
But what does this do exactly?
Let's say a game fetches the base pointer for the player from a static location with code like this:
Code: | ...
48 8B 05 57E2A90D - mov rax,[Game.exe+F6FA348]
48 8B 48 68 - mov rcx,[rax+68]
8B 46 20 - mov eax,[rsi+20]
39 41 18 - cmp [rcx+18],eax
... |
You'll want the address from that mov rax,[Game.exe+F6FA348] instruction. The first three bytes are the instruction, the last four bytes is the address you want.
Tell the function that the address comes at three bytes after the start of the instruction, and pass an AOB string to search for like this:
Code: | playerPointer = getPointerFromCodeAOB( 3, "48 8B 05 ?? ?? ?? ?? 48 8B 48 68 8B 46 20" ) |
The function will return the address Game.exe+F6FA348 as a string and also print it to LUA console.
Or maybe an AOB search is easier when the instruction with the pointer isn't the first one? Consider a case like this:
Code: | ...
66 0F5A C8 - cvtpd2ps xmm1,xmm0
0F57 C0 - xorps xmm0,xmm0
F3 0F5D 0D BC6E8005 - minss xmm1,[Game.exe+75DCC44]
... |
Code: | local aob = "66 0F 5A C8 0F 57 C0 F3 0F 5D 0D ?? ?? ?? ??"
getPointerFromCodeAOB( 4, aob, "Health Cap", 7, true, true ) |
The minss instruction is 4 bytes before the pointer this time, then we search for an AOB with the name "Health Cap" and tell the function to start looking for the pointer instruction 7 bytes from the start of the search to skip the first two instructions.
We set isSilent to true and registerSymbol to true, so the result isn't posted to the console but is immediately registered as a symbol called "Health Cap" in the table.
You can even search for multiple pointers in one go by passing it tables like this:
Code: | local aobList = {
"48 8B 15 ?? ?? ?? ?? 48 85 D2 74",
"48 8B 05 ?? ?? ?? ?? 80 78 62 00 75",
"48 8B 05 ?? ?? ?? ?? 48 85 C0 74",
"48 8B 15 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 15"
}
local aobNames = {
"Player",
"Inventory",
"Weapons",
"Quests"
} |
It will then return a table of strings with the adresses like that, too, or return an empty string if no address was found.
I tried to make it as robust as possible, so the function throws errors if something goes wrong. It will by default scan the currently attached process module, but you can specify a different one too as the processname argument.
How to use or install
Either:
- Create a .lua file in the ..\Cheat Engine\autorun\ folder, then copy & paste the function into it for local use
- Copy & paste the function into the LUA script of a certain table if you want to distribute a table that uses the function for pointer updates.
Code: | --- Get a static pointer from an executable code AOB,
-- for example a "mov rax, [pointer]" instruction
-- can take single AOB strings or an array of AOBs
-- getPointerFromCodeAOB( ins_offset, aobList, OPTIONAL aobNames, OPTIONAL aob_offset, OPTIONAL isSilent, OPTIONAL registerSymbol, OPTIONAL modulename )
-- @param ins_offset: number of bytes from the start of the instruction to the pointer, e.g. for mov rax,[pointer] it's 3 bytes
-- @param aobList: one string of AOB bytes or an array of multiple strings
-- @param aobNames: string or array of names for the AOB pointers
-- @param aob_offset: number of bytes from start of AOB to start of pointer instruction, default 0
-- @param isSilent: suppresses non-error prints to console if true, default false
-- @param registerSymbol: registers a symbol for all AOBs found if true, default false
-- @param modulename: name of the module to search in, formatted like "process.exe"; default is currently attached process module
-- @return string or array of strings with module pointers, returns empty string when not found and false on error
function getPointerFromCodeAOB(...)
if getOpenedProcessID() == 0 then print( "ERROR: Not attached to process!\n" ) return false end
local args = {...}
if #args < 2 then print( "ERROR: getPointerFromCodeAOB needs at least 2 arguments!\n" ) return false end
local aobList, result = {}, {}
if (type(args[2]) == "table") then
aobList = args[2]
else
aobList = {args[2]}
end
local aobNames = args[3]
if (type(args[3]) ~= "table") then
aobNames = {aobNames}
end
for i=1,#aobList do
aobNames[i] = aobNames[i] or 'Pointer '..i
end
local offins = args[1]
local offaob = args[4] or 0
local isSilent = args[5] or false
local doSymbol = args[6] or false
local procname = ( type(args[7])~='string' or (args[7] or '')=='' ) and process or args[7]
if args[7] then
local moduleList = enumModules()
local moduleFound
for _, v in pairs(moduleList) do
if v.Name == procname then moduleFound = true break end
end
if not moduleFound then print(string.format( "ERROR: Specified modulename %s not found!\n",procname )) return false end
end
local pbase = readInteger(procname) and getAddress(procname)
local pend = pbase + getModuleSize(procname)
if type(offins) ~= "number" or type(offaob) ~= "number" then print ( "ERROR: offsets for getPointerFromCodeAOB must be a number! \n" ) return false end
if not isSilent then print(string.format( "Fetching %d pointer(s) for %s ...\n",#aobList,procname )) end
for i = 1, #aobList do
local aob = AOBScan(aobList[i],"+X*C*W")
if aob then
local j = 0
while j < aob.Count do
local adr = getAddressSafe(aob[j])
if adr < pbase or adr >= pend then aob.delete(j) else j = j + 1 end
end
end
if not aob or aob.Count < 1 then
result[i] = ""
if not isSilent then print(string.format( "AOB #%d (%s) not found!",i,aobNames[i] )) end
else
if (aob.Count > 1) and not isSilent then print(string.format("WARNING: %d matches for AOB #%d (%s)! Using first result.",aob.Count,i,aobNames[i])) end
local instruct = getAddressSafe(aob[0])+offaob
local instructSize = getInstructionSize(instruct)
local distance = readInteger( getAddressSafe(instruct)+offins )
local address = ( instruct + instructSize + distance ) - pbase
result[i] = string.format("%s+%X",procname,address)
if not isSilent then print(string.format( "%s: %s+%X",aobNames[i],procname,address) ) end
if doSymbol then registerSymbol( aobNames[i], string.format("%s+%X",procname,address) ) end
end
end
if #aobList == 1 then result = result[1] end
return result
end |
I hope someone might find it useful.
edit 20240920-1: renamed processname parameter to modulename for clarification, added some sanity checking to that parameter to make sure you pass a valid module.
edit 20240920-2: Fixed an error in module scanning: changed for-loop to a while-loop, since LUA has static for-loops that don't handle shrinking tables well.
Last edited by HenryEx on Fri Sep 20, 2024 11:13 am; edited 4 times in total |
|
Back to top |
|
|
xxhehe Expert Cheater Reputation: 0
Joined: 11 Mar 2015 Posts: 147
|
Posted: Sat Sep 14, 2024 9:25 pm Post subject: |
|
|
They are helpful. |
|
Back to top |
|
|
Csimbi I post too much Reputation: 96
Joined: 14 Jul 2007 Posts: 3208
|
Posted: Wed Sep 18, 2024 3:37 pm Post subject: Re: Find static pointers via AOB search in executable code |
|
|
HenryEx wrote: |
I hope someone might find it useful. |
It is.
Any chance to add a new parameter that would limit the memory scan to the executable image?
E.g. only the EXE would be scanned (which is usually small compared to all the memory allocated to the process).
Maybe a module name a'la CE's own aobscanmodule - if provided, pass it to CE and do module scan instead of full aobscan?
Thank you! |
|
Back to top |
|
|
HenryEx Advanced Cheater Reputation: 1
Joined: 18 Dec 2011 Posts: 79
|
Posted: Fri Sep 20, 2024 6:22 am Post subject: Re: Find static pointers via AOB search in executable code |
|
|
Csimbi wrote: | It is.
Any chance to add a new parameter that would limit the memory scan to the executable image?
E.g. only the EXE would be scanned (which is usually small compared to all the memory allocated to the process).
Maybe a module name a'la CE's own aobscanmodule - if provided, pass it to CE and do module scan instead of full aobscan?
Thank you! |
The function already does this by default. It only AOB scans executable code in the first place, and also filters out all addresses that are outside of the module region of the attached process. Or whatever process you specified in the optional processname parameter.
Now that i think about it, that would be a problem for games with dynamically initialized code like mono games.
Also, i guess the processname parameter is kind of a misnomer, since it doesn't change the process that CE is attached to and searches, it only changes the "module region" filter. So you can also look for executable AOBs in a loaded DLL and the like. I suppose calling it the "modulename" parameter would have been more accurate.
edit: actually changed the parameter name, should be clearer now. Also some additional sanity checking to make sure we actually get a name, user still needs to make sure it's valid though.
edit2: Scratch that, actually added check that the module you specify does exist.
edit3: Now that i'm looking over the module range scan, i found more problems. Changing the for loop to a while loop, since for loops are static and don't handle looping through a shrinking table very well. |
|
Back to top |
|
|
Csimbi I post too much Reputation: 96
Joined: 14 Jul 2007 Posts: 3208
|
Posted: Sat Sep 21, 2024 2:21 pm Post subject: Re: Find static pointers via AOB search in executable code |
|
|
HenryEx wrote: |
The function already does this by default. It only AOB scans executable code in the first place, and also filters out all addresses that are outside of the module region of the attached process. Or whatever process you specified in the optional processname parameter.
|
Really? It felt really slow - as if it was scanning the whole memory.
Might be a performance issue then?
No worries, take your time - thanks for doing this! |
|
Back to top |
|
|
xxhehe Expert Cheater Reputation: 0
Joined: 11 Mar 2015 Posts: 147
|
Posted: Sun Sep 22, 2024 7:26 pm Post subject: Re: Find static pointers via AOB search in executable code |
|
|
HenryEx wrote: | Csimbi wrote: | It is.
Any chance to add a new parameter that would limit the memory scan to the executable image?
E.g. only the EXE would be scanned (which is usually small compared to all the memory allocated to the process).
Maybe a module name a'la CE's own aobscanmodule - if provided, pass it to CE and do module scan instead of full aobscan?
Thank you! |
The function already does this by default. It only AOB scans executable code in the first place, and also filters out all addresses that are outside of the module region of the attached process. Or whatever process you specified in the optional processname parameter.
Now that i think about it, that would be a problem for games with dynamically initialized code like mono games.
Also, i guess the processname parameter is kind of a misnomer, since it doesn't change the process that CE is attached to and searches, it only changes the "module region" filter. So you can also look for executable AOBs in a loaded DLL and the like. I suppose calling it the "modulename" parameter would have been more accurate.
edit: actually changed the parameter name, should be clearer now. Also some additional sanity checking to make sure we actually get a name, user still needs to make sure it's valid though.
edit2: Scratch that, actually added check that the module you specify does exist.
edit3: Now that i'm looking over the module range scan, i found more problems. Changing the for loop to a while loop, since for loops are static and don't handle looping through a shrinking table very well. |
If the data to be scanned is in a dll module...... |
|
Back to top |
|
|
HenryEx Advanced Cheater Reputation: 1
Joined: 18 Dec 2011 Posts: 79
|
Posted: Mon Sep 23, 2024 11:28 am Post subject: Re: Find static pointers via AOB search in executable code |
|
|
xxhehe wrote: | If the data to be scanned is in a dll module...... |
Yes, that works. You can specify an AOB for hooking the renderer to add an overlay or whatever and use the modulename parameter to only return results from, for example, "d3d11.dll".
The module / .exe / .dll to scan is case sensitive though, so it MUST be specified exactly as it appears in CE's drop-down menu in Memory Scan Options. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|