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 


Custom Auto Assemble template uses Mono Symbols

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
LewcowVaal
Advanced Cheater
Reputation: 0

Joined: 30 Dec 2017
Posts: 63

PostPosted: Sun Apr 07, 2024 12:36 pm    Post subject: Custom Auto Assemble template uses Mono Symbols Reply with quote

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.
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 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