For Lua Script Templates see this post.
This is an auto assembler template engine that compiles/renders templates, the template engine is based off [Link]. You can access variables and run lua code in the templates using the appropriate tags. There are two file's you'll need to start; "TemplateEngine.lua" and "AutoAssemblerTemplates.lua". You can just stick them both in the "autorun" folder. And you'll need to create the "Templates\cea" Folder (in the "autorun" folder) for the templates. It uses "registerAutoAssemblerTemplate" when loading so they will be in the same menu as the standard CE auto assembler templates.
When CE loads, "AutoAssemblerTemplates" will scan the templates folder for "LoadOrder.lua" if found and it returns a table/array of file names it will load in that order; if not found is will scan the templates folder for any ".CEA" files. When it finds a template file it will also look for "[template file name].settings.lua", the settings file is not required but allows for more control of the template and menu items added to the auto assembler form. The settings file can return a table of the template's settings, but this is not required (more on why later).
For simple output you can use "<<" and ">>" tags, what ever is returned will be converted to string if not already and replace where the open and close tags are; these can be a called function, variable, or just a string/number. For lua code you can use "<%" and "%>" tags, these can be full lua code; thus you can set/create variables, use loops, and if statements.
Here is an archive with the needed files and one example template and setting file.
Using a template file named "My basic template.CEA" like this:
Code: Select all
// Cheat Engine Version: << getCEVersion() >>
<% print('This will print when rendered but will not render in the template.') %>
//------------------------------ ENABLE ------------------------------
[ENABLE]
<% local text = 'here is a local variable created in the template.' %>
<< text >> So that's pretty cool.
// if you need "\<<" or "\<%" to be in the rendered template then you need to escape them.
// A single "<" doesn't need to be escaped, nor do ">>" and "%>".
{$lua}
print('This is in the template and not processed when rendered.')
{$asm}
//------------------------------ DISABLE ------------------------------
[DISABLE]
Code: Select all
// Cheat Engine Version: 7.2
//------------------------------ ENABLE ------------------------------
[ENABLE]
here is a local variable created in the template. So that's pretty cool.
// if you need "<<" or "<%" to be in the rendered template then you need to escape them.
// A single "<" doesn't need to be escaped, nor do ">>" and "%>".
{$lua}
print('This is in the template and not processed when rendered.')
{$asm}
//------------------------------ DISABLE ------------------------------
[DISABLE]
There is another special file named "Header.CEA" which is rendered then passed to the template as "Header":
Code: Select all
<< Header >>
// This allows for a common header without polluting the template file it self
// and can have lua code like the template files.
// But it will be a blank line if there's no header file.
For a settings file for "My basic template.CEA" we can create a file named "My basic template.settings.lua" like this:
Code: Select all
local settings = {
Caption = 'Custom: Basic Template',
Shortcut = 'Ctrl+Alt+1',
}
return settings
Code: Select all
Template Settings:
Caption : string
The caption of the template's menu item.
Shortcut : string
The shortcut of the template's menu item.
AskForInjectionAddress : boolean
Will prompt for a different address than the selected memory view lines if set to true.
Allows the injection point to be offset from the AOB.
AskForHookName : boolean
Will prompt for a hook name if set to true.
InjectionInfoLinesCount : number
Will override the default number of lines in the "InjectionInfo" table.
AppendToHookName : string
Will be appended to the hook name if not already (if "AskForHookName" is true).
WildCard : string/char
Will override the default wild card if set.
Code: Select all
Template Variables:
Address : number
The address of the injection point.
AddressString : string
The address of the injection point as a string. It will be in "module+offset" or hex format.
AobAddress : number
The address of the AOB start (first selected line in the memory view form).
AobAddressString : string
Same as address but for "AobAddress".
OriginalBytes : table/array : number
A table of numbers (base 10) of the original bytes.
OriginalBytesString : string
A string of the original bytes in a "XX XX" (base 16) format.
ModuleName : string
A string of the module name if the injection point and full AOB is in a module.
Signature : string
The AOB in a signature format, for now it just removes hard coded address and 4 byte offsets.
AOB : table/array : number
A table of numbers (base 10) of the raw AOB.
AobOffset : number
The difference between "AobAddress" and "Address" or nil if they are the same.
AobOffsetString : string
The AOB offset in hex format with the appropriate sign (e.g.: "+10" or "-10").
Or nil if there is no aob offset.
PointerDefault : string
Either "dd 0" or "dq 0" based on if the target is 64 bit.
BaseAddressRegistry : string
If opcode in the format of "[reg+n]" is found this would be set to "reg".
OriginalOpcode : table/array : string
A table of strings of the original opcode lines.
InjectionInfo : table/array : string
Disassembler lines before and after the injection point.
NopBytes : table
A table of numbers (base 10) of the nop bytes (i.e.: 0x90) for the injection point
if it's not equal to 5 bytes. It will be an empty table if no nops are needed.
NopBytesString : string
The string of the nop bytes in a "XX XX" (base 16) format.
CEVersion : number
The current CE version.
Date : string
The current date.
HookName : string
If the template settings has "AskForHookName" set to true it will prompt for a hook name.
Then title case the string (e.g.: "some test hook" will be come "Some Test Hook"),
and set this to that.
HookNameParsed : string
If the template settings has "AskForHookName" set to true it will prompt for a hook name.
Then title case and remove spaces in the string
(e.g.: "some test hook" will be come "SomeTestHook"), and set this to that.
FinalCompilation : boolean
Only for the settings files as they get loaded once when CE loads then again at the start
of template rendering to get the template settings, and again just before rendering the
template but only on the last load will the environment be setup.
So this is used to know if the environment is setup if more environment setup is done in
the setting file.
So say you don't like the signature that is generated and you just want to have a string of all the AOB bytes, but you don't want to do this in the template. You can use a settings file like this:
Code: Select all
if FinalCompilation then
local bs = ''
for _, b in ipairs(AOB) do
bs = bs..string.format('%02X ', b)
end
Signature = bs
end
Full Examples:
Example 1
So if "GameTile", "GameFileVersion", and "GameVersion" globals aren't set; and you have a "Header.CEA" file like this:
And a setting file like this (named "AobGetOpcodeAddress.settings.lua"):
And a template file like this (named "AobGetOpcodeAddress.CEA"):
And you select these lines in the memory view form (CE x64 tutorial step 2):
And open the auto assembler form ("Ctrl+A"), and select the "Custom: AOB Get Opcode Address" menu item or press "Ctrl+Alt+8". When prompted for the injection address hit enter (keep first selected line) then when prompted for a hook name you enter "tutorial step 2". You'll get a rendered template like this:
Code: Select all
{
Process : << process >> - << targetIs64Bit() and 'x64' or 'x32' >>
Module : << ModuleName >>
Game Title : << GameTitle >>
Game File Version : << GameFileVersion >>
Game Version : << GameVersion >>
CE Version : << CEVersion >>
Script Version : 1.0.1
Date : << Date >>
Author : ShyTwig16
Name : << HookNameParsed >>
<< HookName >>
}
Code: Select all
if FinalCompilation then
local instLenght = getInstructionSize(Address)
OpcodeAddressOffset = instLenght - 4
end
local settings = {
Caption = 'Custom: AOB Get Opcode Address',
Shortcut = 'Ctrl+Alt+8',
AskForInjectionAddress = true,
AskForHookName = true,
AppendToHookName = 'hook',
}
return settings
Code: Select all
<< Header >>
{$STRICT}
define(address, << AddressString >>)
define(bytes, << OriginalBytesString >>)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]<% if ModuleName then %>
aobScanModule(aob<< HookNameParsed >>, << ModuleName >>, << Signature >>)<% else %>
aobScan(aob<< HookNameParsed >>, << Signature >>)<% end %><% if AobOffsetString then %>
define(inst<< HookNameParsed >>, aob<< HookNameParsed >><< AobOffsetString >>)<% else %>
define(inst<< HookNameParsed >>, aob<< HookNameParsed >>)<% end %>
getOpcodeAddress(ptr<< HookNameParsed >>, inst<< HookNameParsed >>+<< OpcodeAddressOffset >>)
registerSymbol(ptr<< HookNameParsed >>)
////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
unregisterSymbol(inst<< HookNameParsed >>)
unregisterSymbol(ptr<< HookNameParsed >>)
{<% if ModuleName then %>
Module: << ModuleName >>
<% end %>Address: << AddressString >>
AOB Address: << AobAddressString >><% for i, line in ipairs(InjectionInfo) do %>
<< line >><% end %>
}
Code: Select all
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000 - cmp [rbx+000007F0],000003E8 { 1000 }
Tutorial-x86_64.exe+2B3B3 - 75 33 - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000 - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01 - mov dl,01 { 1 }
Code: Select all
{
Process : Tutorial-x86_64.exe - x64
Module : Tutorial-x86_64.exe
Game Title :
Game File Version :
Game Version :
CE Version : 7.2
Script Version : 1.0.1
Date : 12/21/21
Author : ShyTwig16
Name : TutorialStep2Hook
Tutorial Step 2 Hook
}
{$STRICT}
define(address, Tutorial-x86_64.exe+2B3A9)
define(bytes, 81 BB F0 07 00 00 E8 03 00 00)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
aobScanModule(aobTutorialStep2Hook, Tutorial-x86_64.exe, 81BBF0070000xxxxxxxx7533488B8BxxxxxxxxB201)
define(instTutorialStep2Hook, aobTutorialStep2Hook)
getOpcodeAddress(ptrTutorialStep2Hook, instTutorialStep2Hook+6)
registerSymbol(ptrTutorialStep2Hook)
////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
unregisterSymbol(instTutorialStep2Hook)
unregisterSymbol(ptrTutorialStep2Hook)
{
Module: Tutorial-x86_64.exe
Address: Tutorial-x86_64.exe+2B3A9
AOB Address: Tutorial-x86_64.exe+2B3A9
Tutorial-x86_64.exe+2B392 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B394 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B396 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B398 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B39A - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B39C - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B39E - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B3A0 - 53 - push rbx
Tutorial-x86_64.exe+2B3A1 - 48 8D 64 24 E0 - lea rsp,[rsp-20]
Tutorial-x86_64.exe+2B3A6 - 48 89 CB - mov rbx,rcx
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000- cmp [rbx+000007F0],000003E8 <<<---- Injection point
Tutorial-x86_64.exe+2B3B3 - 75 33 - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000 - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01 - mov dl,01
Tutorial-x86_64.exe+2B3BE - 48 8B 83 C0070000 - mov rax,[rbx+000007C0]
Tutorial-x86_64.exe+2B3C5 - 48 8B 00 - mov rax,[rax]
Tutorial-x86_64.exe+2B3C8 - FF 90 40040000 - call qword ptr [rax+00000440]
Tutorial-x86_64.exe+2B3CE - 48 8B 8B E0070000 - mov rcx,[rbx+000007E0]
Tutorial-x86_64.exe+2B3D5 - 30 D2 - xor dl,dl
Tutorial-x86_64.exe+2B3D7 - 48 8B 83 E0070000 - mov rax,[rbx+000007E0]
Tutorial-x86_64.exe+2B3DE - 48 8B 00 - mov rax,[rax]
}
Example 2
With the same header file as example 1.
And a setting file like this (named "AobFullInjection.settings.lua"):
And a template file like this (named "AobFullInjection.CEA"):
And you select these lines in the memory view form (CE x64 tutorial step 2):
And open the auto assembler form ("Ctrl+A"), and select the "Custom: AOB Full Injection" menu item or press "Ctrl+Alt+6". When prompted for the injection address you enter this address "Tutorial-x86_64.exe+2B3A9" then when prompted for a hook name you enter "tutorial step 2". You'll get a rendered template like this:
And a setting file like this (named "AobFullInjection.settings.lua"):
Code: Select all
local settings = {
Caption = 'Custom: AOB Full Injection',
Shortcut = 'Ctrl+Alt+6',
AskForInjectionAddress = true,
AskForHookName = true,
AppendToHookName = 'hook',
}
return settings
Code: Select all
<< Header >>
{$STRICT}
define(address, << AddressString >>)
define(bytes, << OriginalBytesString >>)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]<% if ModuleName then %>
aobScanModule(aob<< HookNameParsed >>, << ModuleName >>, << Signature >>)<% else %>
aobScan(aob<< HookNameParsed >>, << Signature >>)<% end %><% if AobOffsetString then %>
define(inj<< HookNameParsed >>, aob<< HookNameParsed >><< AobOffsetString >>)<% else %>
define(inj<< HookNameParsed >>, aob<< HookNameParsed >>)<% end %>
assert(inj<< HookNameParsed >>, bytes)
registerSymbol(inj<< HookNameParsed >>)
alloc(mem<< HookNameParsed >>, 0x400, inj<< HookNameParsed >>)
label(ptr<< HookNameParsed >>)
registerSymbol(ptr<< HookNameParsed >>)
label(n_code)
label(o_code)
label(exit)
label(return)
mem<< HookNameParsed >>:
ptr<< HookNameParsed >>:
<< PointerDefault >>
align 10 CC
n_code:
mov [ptr<< HookNameParsed >>],<< BaseAddressRegistry >>
o_code:<% for i, line in ipairs(OriginalOpcode) do %>
<< line >><% end %>
exit:
jmp return
////
//// ---------- Injection Point ----------
inj<< HookNameParsed >>:
jmp n_code<% for _, _ in ipairs(NopBytes) do %>
nop<% end %>
return:
////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
////
//// ---------- Injection Point ----------
inj<< HookNameParsed >>:
db bytes
unregisterSymbol(inj<< HookNameParsed >>)
unregisterSymbol(ptr<< HookNameParsed >>)
dealloc(mem<< HookNameParsed >>)
{<% if ModuleName then %>
Module: << ModuleName >>
<% end %>Address: << AddressString >>
AOB Address: << AobAddressString >><% for i, line in ipairs(InjectionInfo) do %>
<< line >><% end %>
}
Code: Select all
Tutorial-x86_64.exe+2B3A6 - 48 89 CB - mov rbx,rcx
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000 - cmp [rbx+000007F0],000003E8 { 1000 }
Tutorial-x86_64.exe+2B3B3 - 75 33 - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000 - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01 - mov dl,01 { 1 }
Code: Select all
{
Process : Tutorial-x86_64.exe - x64
Module : Tutorial-x86_64.exe
Game Title :
Game File Version :
Game Version :
CE Version : 7.2
Script Version : 1.0.1
Date : 12/21/21
Author : ShyTwig16
Name : TutorialStep2Hook
Tutorial Step 2 Hook
}
{$STRICT}
define(address, Tutorial-x86_64.exe+2B3A9)
define(bytes, 81 BB F0 07 00 00 E8 03 00 00)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
aobScanModule(aobTutorialStep2Hook, Tutorial-x86_64.exe, 4889CB81BBF0070000xxxxxxxx7533488B8BxxxxxxxxB201)
define(injTutorialStep2Hook, aobTutorialStep2Hook+3)
assert(injTutorialStep2Hook, bytes)
registerSymbol(injTutorialStep2Hook)
alloc(memTutorialStep2Hook, 0x400, injTutorialStep2Hook)
label(ptrTutorialStep2Hook)
registerSymbol(ptrTutorialStep2Hook)
label(n_code)
label(o_code)
label(exit)
label(return)
memTutorialStep2Hook:
ptrTutorialStep2Hook:
dq 0
align 10 CC
n_code:
mov [ptrTutorialStep2Hook],rbx
o_code:
cmp [rbx+000007F0],000003E8
exit:
jmp return
////
//// ---------- Injection Point ----------
injTutorialStep2Hook:
jmp n_code
nop
nop
nop
nop
nop
return:
////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
////
//// ---------- Injection Point ----------
injTutorialStep2Hook:
db bytes
unregisterSymbol(injTutorialStep2Hook)
unregisterSymbol(ptrTutorialStep2Hook)
dealloc(memTutorialStep2Hook)
{
Module: Tutorial-x86_64.exe
Address: Tutorial-x86_64.exe+2B3A9
AOB Address: Tutorial-x86_64.exe+2B3A6
Tutorial-x86_64.exe+2B392 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B394 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B396 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B398 - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B39A - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B39C - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B39E - 00 00 - add [rax],al
Tutorial-x86_64.exe+2B3A0 - 53 - push rbx
Tutorial-x86_64.exe+2B3A1 - 48 8D 64 24 E0 - lea rsp,[rsp-20]
Tutorial-x86_64.exe+2B3A6 - 48 89 CB - mov rbx,rcx <<<---- AOB
Tutorial-x86_64.exe+2B3A9 - 81 BB F0070000 E8030000- cmp [rbx+000007F0],000003E8 <<<---- Injection point
Tutorial-x86_64.exe+2B3B3 - 75 33 - jne Tutorial-x86_64.exe+2B3E8
Tutorial-x86_64.exe+2B3B5 - 48 8B 8B C0070000 - mov rcx,[rbx+000007C0]
Tutorial-x86_64.exe+2B3BC - B2 01 - mov dl,01
Tutorial-x86_64.exe+2B3BE - 48 8B 83 C0070000 - mov rax,[rbx+000007C0]
Tutorial-x86_64.exe+2B3C5 - 48 8B 00 - mov rax,[rax]
Tutorial-x86_64.exe+2B3C8 - FF 90 40040000 - call qword ptr [rax+00000440]
Tutorial-x86_64.exe+2B3CE - 48 8B 8B E0070000 - mov rcx,[rbx+000007E0]
Tutorial-x86_64.exe+2B3D5 - 30 D2 - xor dl,dl
Tutorial-x86_64.exe+2B3D7 - 48 8B 83 E0070000 - mov rax,[rbx+000007E0]
Tutorial-x86_64.exe+2B3DE - 48 8B 00 - mov rax,[rax]
}