LewcowVaal Advanced Cheater Reputation: 0
Joined: 30 Dec 2017 Posts: 63
|
Posted: Sun Apr 07, 2024 12:36 pm Post subject: Custom Auto Assemble template uses Mono Symbols |
|
|
Following my previous post ( https://forum.cheatengine.org/viewtopic.php?t=622250 )
I managed to find and edit a template that works.
However, if Mono features are active and i let the Auto Assemble use my template, it will use the Mono Symbols, thus failing or even throwing errors.
Same goes for the originalcode part (it uses the Mono symbols instead of the actual addresses).
Otherwise, if Mono Features are not active, it works properly.
The default AOB Injection template of CE uses the actual Addresses regardless of the Mono activation. I dug into the GitHub repo and managed to find only a .pas file containing the source code for it, but eventually i came across a .lua template that i modified (i just modified the first part of it, not the actual script generation)
This is the .lua
Code: |
myAOBInjectionTemplates = {}
myAOBInjectionTemplates.Templates = {
{
displayName="AOB Injection Custom",
submenu='Test',
templateSections=
[==[
<<ENABLE>>
{$LUA}
if not getAddressSafe("aob_%cheatName%") then
return [[
aobscan(aob_%cheatName%, %moduleNameC%%searchPattern%)
registersymbol(aob_%cheatName%)
]]
end
{$ASM}
alloc(newmem_%cheatName%,$1000%CmoduleName%)
label(return_%cheatName%)
newmem_%cheatName%:
%_originalCodeLines%
jmp return_%cheatName%
aob_%cheatName%%aobAdjust%:
jmp newmem_%cheatName%
%_nopLines%
return_%cheatName%:
<<ENABLE_END>>
<<DISABLE>>
aob_%cheatName%%aobAdjust%:
db %originalBytes%
dealloc(newmem_%cheatName%)
%additionalInfo%
<<DISABLE_END>>
]==]
}
}
local extensionVersion = '1.3.6'
function myAOBInjectionTemplates.formCreateNotify(form)
if form.ClassName~="TfrmAutoInject" then return end
local timer=createTimer()
timer.Interval=100
timer.OnTimer = function (t)
if (form.Menu==nil) then return end
t.destroy()
myAOBInjectionTemplates.addMenuEntries(form)
end
end
function myAOBInjectionTemplates.addMenuEntries(form)
local m,mi,sm=form.emplate1,nil,nil
local createdSubmenus={}
local lastMenuItemFromGroup={}
local smIndex = 1
mi = createMenuItem(m); m.add(mi); mi.Caption = '-' -- separator
for i=1,#myAOBInjectionTemplates.Templates do
local submenu = myAOBInjectionTemplates.Templates[i].submenu
local group = myAOBInjectionTemplates.Templates[i].group
local groupname=(submenu or '')..(group or '')
if submenu~=nil then
if createdSubmenus[submenu] then
sm=createdSubmenus[submenu]
else
sm = createMenuItem(m); m.add(sm)
sm.Caption = submenu
sm.Name = 'miAlternativeAOBtemplateSubmenu'..smIndex; smIndex=smIndex+1
createdSubmenus[submenu]=sm
end
else
sm=m
end
if lastMenuItemFromGroup[groupname]==nil then
if sm.Count>0 then
mi = createMenuItem(m); sm.add(mi); mi.Caption = '-' -- separator
end
mi = createMenuItem(m); sm.add(mi)
lastMenuItemFromGroup[groupname]=mi
else
mi = createMenuItem(m); sm.insert(lastMenuItemFromGroup[groupname].MenuIndex+1, mi)
lastMenuItemFromGroup[groupname]=mi
end
mi.OnClick = function (sender)
myAOBInjectionTemplates.generate(sender,myAOBInjectionTemplates.Templates[i])
end
mi.Caption = myAOBInjectionTemplates.Templates[i].displayName
mi.Name = 'miAlternativeAOBtemplate'..i
end
end
registerFormAddNotification(myAOBInjectionTemplates.formCreateNotify)
function myAOBInjectionTemplates.generate(sender,chosenTemplate)
local displayName = chosenTemplate.displayName
local cheatName = chosenTemplate.defaultSymbolName or 'example'
local template = chosenTemplate.templateSections
local form=sender.Owner.Owner
local origScript = form.Assemblescreen.Lines.Text
--gather existing names from origScript from registersymbol
local existingNames = {}
for existingName in origScript:gmatch('registersymbol%(%s*(.-)%s*%)') do
existingNames[1+#existingNames] = existingName
end
-- also from define
for existingName in origScript:gmatch('define%(%s*(.-)%s*,') do
existingNames[1+#existingNames] = existingName
end
local function checkForCollides(str)
for i,v in ipairs(existingNames) do
if v:find(str, 1, true)~=nil then return 'Name "'..str..'" collides with existing "'..v..'"' end
if str:find(v, 1, true)~=nil then return 'Existing "'..v..'" collides with name "'..str..'"' end
end
return nil
end
local address = 0
if form.owner.DisassemblerView then
address = form.owner.DisassemblerView.SelectedAddress
else
address = getMemoryViewForm().DisassemblerView.SelectedAddress
end
--try to find module name+offset
local selectedAddress = getNameFromAddress(address)
local modulesTable,size = enumModules(),0
local exeVersionStr = ''
local moduleVersionStr=''
for i,v in pairs(modulesTable) do
size = getModuleSize(v.Name)
if size~=nil and (address>=v.Address and address<=v.Address+size)
then
if i~=1 then
local _,moduleVersionTbl = getFileVersion(v.PathToFile)
moduleVersionStr = moduleVersionTbl==nil and '' or (moduleVersionTbl.major..'.'..moduleVersionTbl.minor..'.'..
moduleVersionTbl.release..'.'..moduleVersionTbl.build)
end
selectedAddress = '"'..v.Name..'"+'..string.format('%X',address-v.Address)
break
end
end
local _,exeVersionTbl = getFileVersion(modulesTable[1].PathToFile)
local exeVersionStr = exeVersionTbl==nil and '' or (exeVersionTbl.major..'.'..exeVersionTbl.minor..'.'..
exeVersionTbl.release..'.'..exeVersionTbl.build)
selectedAddress=inputQuery(displayName,'On what address do you want the jump?', selectedAddress)
if selectedAddress==nil then return end
cheatName=inputQuery(displayName,'What do you want to name the symbol for the injection point?', cheatName)
if cheatName==nil then return end
::setValidname:: --do not allow default name or those already existing/colliding or empty
while cheatName:lower()=='inject' or
cheatName=='' do
cheatName=inputQuery('Caution!', 'Ugly name. Change it.', cheatName) or ''
cheatName=cheatName:gsub('%s','') -- remove spaces
end
-- check if already exist or collides with each other
local collides = checkForCollides(cheatName)
if collides~=nil then
cheatName=inputQuery('Caution!', collides..'. Change it.', cheatName) or ''
cheatName=cheatName:gsub('%s','') -- remove spaces
goto setValidname
end
local newScript_stringlist = createStringlist()
local gaobisResult = generateAOBInjectionScript(newScript_stringlist, cheatName, selectedAddress)
local newScript = newScript_stringlist.Text
newScript_stringlist.destroy()
-- is process opened?
if newScript:match('No Process Selected') then showMessage("No process selected!") return end
-- is aob unique?
if newScript:match('Could not find unique AOB') then
showMessage("Warning. Could not find unique AOB.")
newScript = newScript:gsub('ERROR: Could not find unique AOB,','ERROR: Could not find unique AOB;')
end
if not gaobisResult
then showMessage("generateAOBInjectionScript raised exception!") return end
-- note: 'origScript' and 'newScript' will have "carriage return & line feed" at the end of each line
-- because it is taken from TStrings object.
-- 'template' has only "line feed"
local authorName = newScript:match('Author : (.-)\r\n')
local processName = newScript:match('Game : (.-)\r\n')
local scriptDate = newScript:match('Date : (.-)\r\n')
local isModuleScan = newScript:match('aobscan(module)') or ''
local searchPattern = newScript:match('aobscan.-%(.*,(.-)%) // should be unique')
local moduleName, moduleName_comma, comma_moduleName
if isModuleScan=='module' then
moduleName = newScript:match('aobscan.-%(.-,(.-),.-%)')
moduleName_comma = moduleName..','
comma_moduleName = ','..moduleName
else
moduleName = ''
moduleName_comma = ''
comma_moduleName = ''
end
local _originalCodeLines = newScript:match('code:\r\n(.-)\r\n jmp return')
local aobAdjust = newScript:match('code:.-jmp return\r\n\r\n'..cheatName..'(.-):')
local _nopLines = newScript:match(' jmp code\r\n(.-)\r\nreturn:') or ''
if _nopLines=='' then -- other case
_nopLines = newScript:match(' jmp newmem\r\n(.-)\r\nreturn:') or ''
end
local originalBytes = newScript:match(' db (.-)\r\n')
local additionalInfo = newScript:match('{\r\n// ORIGINAL CODE %- INJECTION POINT.*')
local origfirstLine = (_originalCodeLines..'\r\n'):match( "(.-)\r\n" )
local bracketsRegsOffset = origfirstLine:match('[dq]?word ptr %[.-%]')
or origfirstLine:match('byte ptr %[.-%]')
or origfirstLine:match('%[.-%]')
or ''
local regsOffset = origfirstLine:match('%[(.-)%]') or ''
local originalCodeLines = _originalCodeLines:sub(3):gsub('\r\n ','\r\n') -- indent less version
local nopLines = _nopLines=='' and '' or _nopLines:sub(3):gsub('\r\n ','\r\n') -- indent less version
local CoriginalCodeLines = '//Alt: '.._originalCodeLines:sub(3):gsub('\r\n ','\r\n//Alt: ')-- commented version
local db90s=''
if _nopLines~='' then
if _nopLines:match(' nop (%x+)') then --CE7.0 and above has ' nop '+inttohex(NopCount)
local nopNumber = tonumber(_nopLines:match(' nop (%x+)'),16)
db90s = 'db'..string.rep(" 90", nopNumber)
else --up to CE6.8.3
db90s = 'db'..(nopLines..'\r\n'):gsub('nop\r\n',' 90')
end
end
local _,replacedInstructionsSize = originalBytes:gsub('%x%x','')
local replacedInstructionsSizeHex = string.format('%X',replacedInstructionsSize)
--Mono & Hook Address
local injectAddress = newScript:match('INJECTING HERE %-%-%-%-%-%-%-%-%-%-\r\n(.-):')
local injectAddressNum = getAddress(injectAddress)
local monoAddress = ''
if template:find('%%monoAddress%%') then -- remove lag for templates without mono
if LaunchMonoDataCollector~=nil and LaunchMonoDataCollector()~=0 then
monoAddress = mono_addressLookupCallback(injectAddressNum) or ''
end
end
--reassembleReplacedInstructions
local tmp = getInstructionSize(injectAddressNum)
local reassembleReplacedInstructions = 'reassemble(~)'
while tmp < replacedInstructionsSize do
reassembleReplacedInstructions = reassembleReplacedInstructions .. '\nreassemble(~+'..string.format('%X',tmp)..')'
tmp = tmp + getInstructionSize(injectAddressNum+tmp)
end
-- use the template
template = template:gsub('%%cheatName%%', cheatName)
template = template:gsub('%%authorName%%', authorName)
template = template:gsub('%%processName%%', processName)
template = template:gsub('%%isModuleScan%%', isModuleScan)
template = template:gsub('%%searchPattern%%', searchPattern)
template = template:gsub('%%CmoduleName%%', comma_moduleName)
template = template:gsub('%%moduleNameC%%', moduleName_comma)
template = template:gsub('%%moduleName%%', moduleName)
template = template:gsub('%%replacedInstructionsSize%%', replacedInstructionsSize)
template = template:gsub('%%replacedInstructionsSizeHex%%', replacedInstructionsSizeHex)
template = template:gsub('%%_originalCodeLines%%', _originalCodeLines)
template = template:gsub('%%originalCodeLines%%', originalCodeLines)
template = template:gsub('%%CoriginalCodeLines%%', CoriginalCodeLines)
template = template:gsub('%%originalBytes%%', originalBytes)
template = template:gsub('%%aobAdjust%%', aobAdjust)
template = template:gsub('%%additionalInfo%%', additionalInfo)
template = template:gsub('%%bracketsRegsOffset%%', bracketsRegsOffset)
template = template:gsub('%%regsOffset%%', regsOffset)
template = template:gsub('%%injectAddress%%', injectAddress)
template = template:gsub('%%monoAddress%%', monoAddress)
template = template:gsub('%%reassembleReplacedInstructions%((.-)%)%%', function (a)
return reassembleReplacedInstructions:gsub('~',a)
end)
template = template:gsub('%%scriptDate%%', scriptDate)
template = template:gsub('%%exeVersion%%', exeVersionStr)
template = template:gsub('%%moduleVersion%%', moduleVersionStr)
if db90s~='' then
template = template:gsub('%%nopLines%%', nopLines)
template = template:gsub('%%_nopLines%%', _nopLines)
template = template:gsub('%%db90s%%', db90s)
else
-- remove whole line when NOP'ing is not needed
template = template:gsub('%%nopLines%%.-\n', '')
template = template:gsub('%%_nopLines%%.-\n', '')
template = template:gsub('%%db90s%%.-\n', '')
end
template = template:gsub('%%extensionVersion%%', extensionVersion)
local enablePart = template:match('<<ENABLE>>.(.*).<<ENABLE_END>>')
local disablePart = template:match('<<DISABLE>>.(.*).<<DISABLE_END>>')
local infoPart = template:match('<<INFO>>.(.*).<<INFO_END>>')
if origScript=='\r\n' then origScript='' end --after manually deleting all lines, there's always one empty line
local pos=origScript:find('%[DISABLE]')
if pos then newScript=origScript:sub(1,pos-1)..'\r\n'..enablePart..'\r\n'..origScript:sub(pos)..'\r\n'..disablePart
else newScript=origScript..'[ENABLE]\r\n'..enablePart..'\r\n[DISABLE]\r\n'..disablePart
end
if pos==nil and infoPart~=nil then newScript=infoPart..'\r\n'..newScript end
form.Assemblescreen.Lines.Text = newScript -- update
end
|
I suppose the --Mono & Hook Address section is the culprit, but honestly i have no clue about it.
Edit: I found another post where the issue was already being discussed.
|
|