Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


LUA expert needed: AOB scan at derived address

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Wed Jan 18, 2023 5:39 am    Post subject: LUA expert needed: AOB scan at derived address Reply with quote

Hi all,
I am looking for LUA expert support to create a specific scriptlet.

The basic requirement is, do an AOB script to find an instruction, and then, do another AOB scan based on where that ASM instruction "points". A few examples of these instructions:
Quote:
mov eax,[process.exe+12345678]
mov rax,[7FFF12345678]
jmp 0C
je FFFFFFF4
jne 7FFF12345678
call 12345678
call 7FFF12345678


mgr.inz.Player has already built his excellent find_Nth_Result_AOB scriptlet.
I figured this could be used as the framework to improve upon, because this scriptlet does the first part (that is, find a signature, and continue with another scan from there).

This is an example on how mgr.inz.Player's scriptlet is used:
Code:
aobscanmodule(aobHeroBattleStatPointsUpdater,Battlecry III.exe,83 E9 01 8B 55 ?? 66 89 8A ?? ?? 00 00 8B 4D ?? E8)
LuaCall(find_Nth_Result_AOB('aobHeroBattleSkillPointsUpdater',2,[=[aobHeroBattleStatPointsUpdater]=],"83 E9 01 8B 55 ?? 66 89 8A ?? ?? 00 00 8B 4D ?? E8"))


I imagine I would use this new scriptlet more or less the same way, but this time the AOB scan would not just simply "continue at that address until Nth result is found", rather, it would evaluate the "point" in the instruction found in the initial scan and then, continue scanning for the first result based on where that instruction "points":
Code:
aobscanmodule(SignatureToInstruction,Battlecry III.exe,E8 ?? ?? ?? ?? 8B 8D ?? ?? ?? ?? 81 C1)
LuaCall(instuction_based_AOB('InstructionBasedAOBResult',[=[SignatureToInstruction]=],"E8 ?? ?? ?? ?? 8B 8D ?? ?? ?? ?? 81 C1"))


CE's reassemble(...) instruction can rebuild instructions elsewhere. I figured tapping into that mechanism somehow - or an adaptation of it - could be used to generate the effective address for the second AOB scan, be it x86 or x64 instruction.

I guess the real challenge here is figuring out what the "continuation point" is from the instruction.

Is it clear what I'm asking?
Can anyone help scripting this?

Thank you!


Last edited by Csimbi on Thu Jan 19, 2023 7:59 am; edited 1 time in total
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 54

Joined: 01 Oct 2008
Posts: 941

PostPosted: Wed Jan 18, 2023 8:31 am    Post subject: Reply with quote

May check https://forum.cheatengine.org/viewtopic.php?t=606262
Note that single quote usage in Calc, eg, 'addrStr' (where addrStr is an AA symbol to be expanded), should be change to [[addrStr]] or [=[addrStr]=] as the script was written when I was using a buggy ce version.
May no longer work tho, sorry in this case.

_________________
- Retarded.
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 92

Joined: 14 Jul 2007
Posts: 3102

PostPosted: Thu Jan 19, 2023 5:55 am    Post subject: Reply with quote

Here is my attempt. It demonstrates how clueless I really am Wink - stitching together from code found on the interwebz and mgr.inz.Player's legacy.
I'd really like just a simple, stateless call.
I feel it's not quite reliable - that 'instruction to pointer' conversion should be made more reliable somehow.
Any thoughts?

LUA script:
Code:

-- Author: Csimbi
-- Source: https://forum.cheatengine.org/viewtopic.php?p=5782638#5782638
-- Usage:
--  - Copy this LUA file into CE's autorun folder
--  - Put a line with the LUACall right under your first AOB scan with your seconds scan.
-- The first symbol must be an AOB scan result, addressing the instruction from which the next scan's start address is derived.
-- The second symbol will be registered only when it was successfully found.
-- The plain version scans all memory, but I doubt this is what most people will want, hence the _N version.
-- The _N version allows you to limit the AOB scan to certain number of bytes.
-- You really should be using the _N version because you already know what you are looking for, and where :D
--
-- The script can pick up addresses from instructions like these:
--   jmp 0C
--   je FFFFFFF4
--   jne 7FFF12345678
--   call 12345678
--   call 7FFF12345678
--   call [7FFF12345678]
--
--- AA example:
-- [ENABLE]
-- aobscan(myFirstAOBScan,72 ?? 67 ?? 61 6D ??)
-- LuaCall(do_AOB_scan_at_derived_address('mySecondAOBScan',[=[myFirstAOBScan]=],"80 68 ?? AB F4 6A ?? 72"))
--
-- Alternatively, if you want to limit the search window to 255 bytes (0xFF) - which, You really should.
-- LuaCall(do_AOB_scan_at_derived_address_N('mySecondAOBScan',[=[myFirstAOBScan]=],'0xFF',"80 68 ?? AB F4 6A ?? 72"))
--
-- Notes:
--  - Your initial AOB scan may be of any type of AOB scan; the subsequent scan (LuaCall) will continue from the 'address' derived from the instruction.
--  - The 'mySecondAOBScan' will be registered for you, remember to unregister it when you no longer need it.
--  - You can use 'myFirstAOBScan' instead of 'mySecondAOBScan', too; but then you lose the previous scan's address (which is okay if you don't need it).

function derive_real_address_from_registered_instruction(registered_instruction)
   local sRetVal, temp, iAddress, sInstruction, iAddr, iPtr
   local sAddress, sBytes, sOpcode, sExtraField
   --print('LUACall: derive_real_address_from_instruction')
   if registered_instruction==' 00000000' then return nil end
   iAddress=getAddressSafe(registered_instruction)
   if iAddress==nil then return nil; end
   if getInstructionSize(iAddress)<2 then return nil end
   sInstruction=disassemble(iAddress)
   --print('Disassembly: '..sInstruction)
   if sInstruction==nil or sInstruction=="" then return nil end
   sExtraField, sOpcode, sBytes, sAddress=splitDisassembledString(sInstruction)
   --print('Address: '..sAddress)
   --print('Bytes: '..sBytes)
   --print('Opcode: '..sOpcode)
   --print('ExtraField: '..sExtraField)
   sOpcode=sOpcode:sub(1,-1):gsub("^%s*(.-)%s*$", "%1") -- trim it
   if sOpcode==nil or sOpcode=="" then return nil end
   temp, sOpcode=string.match(sOpcode, "(.-)%s(%S+)$") -- get last word
   --print('Result: '..sOpcode)
   if sOpcode:find( "%[" ) then
     sDerivedAddress=sOpcode:sub(2)            -- cut first char
     sDerivedAddress=sDerivedAddress:sub(1,-2) -- cut last char
     iAddr=tonumber(sDerivedAddress,16)
     --print('iAddr: '..string.format("%X",iAddr))
     iPtr=readPointer(iAddr)
     sRetVal=string.format("%X",iPtr)
   else
     sRetVal=sOpcode
   end
   --print('-----')
   return sRetVal
end

function do_AOB_scan_at_derived_address(symbol, registered_instruction, pattern)
   local sDerivedAddress
   --print('LUACall: do_AOB_scan_at_derived_address')
   sDerivedAddress=derive_real_address_from_registered_instruction(registered_instruction)
   if sDerivedAddress==nil then print('Could not derive address from instruction at address.'); return end
   --print('sDerivedAddress: '..sDerivedAddress)
   local script='aobscanregion('..symbol..','..sDerivedAddress..',7fffffffffffffff,'..pattern..')\r\nregistersymbol('..symbol..')'
   local success=autoAssemble(script)
   if not success then unregisterSymbol(symbol); print('AOB result was not found for '..symbol..' using signature: \r\n'..pattern..'\r\nbetween '..sDerivedAddress..' and 0x7fffffffffffffff.'); error() end
   --print('-----')
   end

function do_AOB_scan_at_derived_address_N(symbol, registered_instruction, limit, pattern)
   local sDerivedAddress
   --print('LUACall: do_AOB_scan_at_derived_address_N')
   if limit==nil or limit=="" then end
   sDerivedAddress=derive_real_address_from_registered_instruction(registered_instruction)
   if sDerivedAddress==nil then print('Could not derive address from instruction at address.'); return end
   --print('sDerivedAddress: '..sDerivedAddress)
   local script='aobscanregion('..symbol..','..sDerivedAddress..','..sDerivedAddress..'+'..limit..','..pattern..')\r\nregistersymbol('..symbol..')'
   local success=autoAssemble(script)
   if not success then unregisterSymbol(symbol); print('AOB result was not found for '..symbol..' using signature: \r\n'..pattern..'\r\nbetween '..sDerivedAddress..' and '..sDerivedAddress..'+'..limit..'.'); error() end
   --print('-----')
end


Usage example:
Code:

[ENABLE]
/* Sample signature at Calculator.exe+54
Calculator.exe+54 - 72 6F                 - jb Calculator.exe+C5 <- AOB Signature; 72 ?? 67 ?? 61 6D ??
Calculator.exe+56 - 67 72 61              - jb Calculator.exe+BA
Calculator.exe+59 - 6D                    - insd
Calculator.exe+5A - 20 63 61              - and [rbx+61],ah
*/

/* The jump above in the signature points here, so the second scan should start here.
Calculator.exe+C5 - 81 68 74 ABF46175     - sub [rax+74],7561F4AB
Calculator.exe+CC - 02 80 6874ABF4        - add al,[rax-0B548B98]
Calculator.exe+D2 - 68 75728068           - push 68807275
Calculator.exe+D7 - 74 AB                 - je Calculator.exe+84
Calculator.exe+D9 - F4                    - hlt
Calculator.exe+DA - 97                    - xchg eax,edi
Calculator.exe+DB - 74 72                 - je Calculator.exe+14F
Calculator.exe+DD - 80 68 74 AB           - sub byte ptr [rax+74],-55 <- second AOB signature; 80 68 ?? AB F4 6A ?? 72
Calculator.exe+E1 - F4                    - hlt
Calculator.exe+E2 - 6A 75                 - push 75
Calculator.exe+E4 - 72 80                 - jb Calculator.exe+66
*/

// First, we find our initial signature.
aobscanmodule(aobFirstSig,Calculator.exe,72 ?? 67 ?? 61 6D ??)

// Second, we ask LUA real nice to evaluate the instruction there, and do an AOB scan for our second signature at the location 'pointed to'.
//LuaCall(do_AOB_scan_at_derived_address('aobSecondSig',[=[aobFirstSig]=],"80 68 ?? AB F4 6A ?? 72"))
LuaCall(do_AOB_scan_at_derived_address_N('aobSecondSig',[=[aobFirstSig]=],'0xFF',"80 68 ?? AB F4 6A ?? 72"))

{$asm}

label(aobFirstSig_r)
registersymbol(aobFirstSig_r)

//7FF7DCDA0056:
aobFirstSig:
aobFirstSig_r: // We just test registration

aobSecondSig: // We just test registration


[DISABLE]
//7FF7DCDA0056:
//Alt: jb 7FF7DCDA00C5
//Alt: jb 7FF7DCDA00BA
//db 72 6F 67 72 61

unregistersymbol(aobSecondSig)
unregistersymbol(*)
dealloc(*)



DoAOBScanAtDerivedAddress.lua
 Description:

Download
 Filename:  DoAOBScanAtDerivedAddress.lua
 Filesize:  4.79 KB
 Downloaded:  118 Time(s)

Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites