|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Csimbi I post too much Reputation: 92
Joined: 14 Jul 2007 Posts: 3102
|
Posted: Wed Jan 18, 2023 5:39 am Post subject: LUA expert needed: AOB scan at derived address |
|
|
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 |
|
|
panraven Grandmaster Cheater Reputation: 54
Joined: 01 Oct 2008 Posts: 941
|
Posted: Wed Jan 18, 2023 8:31 am Post subject: |
|
|
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 |
|
|
Csimbi I post too much Reputation: 92
Joined: 14 Jul 2007 Posts: 3102
|
Posted: Thu Jan 19, 2023 5:55 am Post subject: |
|
|
Here is my attempt. It demonstrates how clueless I really am - 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(*)
|
Description: |
|
Download |
Filename: |
DoAOBScanAtDerivedAddress.lua |
Filesize: |
4.79 KB |
Downloaded: |
118 Time(s) |
|
|
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
|
|