Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[====================================================================================================================[
- I2 Cheat Engine CEA File Assembler
- Version: 2.1.1
- 1.0.1:
- * First release.
- 1.0.2:
- * Fixed load error.
- 1.0.3:
- * Added reset function, to reset the state of all assembled scripts.
- * Changed "autoAssembleFile" to work as toggle, with optional "forceDisable".
- 2.0.1:
- * Reworked to work with "memrec" variable.
- 2.0.2:
- * Fixed Toggle Error.
- 2.0.4:
- * Fixed assebling error clear the disassembly info.
- 2.1.1:
- * Added "getOpcodeAddress" Lua and AA functions.
- Author: Matt - TheyCallMeTim13 - MattI2.com
- Features:
- - A Lua module for assembling CEA files be it, table files or local files, in a Cheat Engine table.
- Note: Local files will override the table files, this is meant for updating scripts.
- - Really the only function meant to be used is autoAssembleFile(ceaFile, targetSelf, disable)
- Settings:
- CEAFilesDirectory : The directory to check for local files.
- Can be set to nil to look in current folder.
- i.e.: 'ceaFiles'
- Install / Setup Method:
- This is a Lua module so place it in the Cheat Engine 'lua' folder or in the same directory as the cheat table
- then just import (require) the module to use
- Examples:
- require 'I2CETableCEA'
- I2CETableCEA.autoAssembleFile('CoordHook.CEA', memrec)
- Note:
- The "Table Require" template in my "pluginI2CELuaScriptTemplateGenerator.lua" plug-in will also allow for
- Lua modules to be added as table files then imported, but local files will override the table files.
- Table Require Code:
- --------
- -------- CE Table Require
- --------
- local TableLuaFilesDirectory = 'luaFiles'
- function CETrequire(moduleStr)
- if moduleStr ~= nil then
- local localTableLuaFilePath = moduleStr
- if TableLuaFilesDirectory ~= nil or TableLuaFilesDirectory ~= '' then
- local sep = package.config:sub(1,1)
- localTableLuaFilePath = TableLuaFilesDirectory .. sep .. moduleStr
- end
- local f, err = io.open(localTableLuaFilePath .. '.lua')
- if f and not err then
- f:close()
- return require(localTableLuaFilePath)
- else
- local tableFile = findTableFile(moduleStr .. '.lua')
- if tableFile == nil then
- return nil
- end
- local stream = tableFile.getData()
- local fileStr = nil
- local bytes = stream.read(stream.Size)
- for i = 1, #bytes do
- if fileStr == nil then
- fileStr = ''
- end
- fileStr = fileStr .. string.char(bytes[i])
- end
- if fileStr then
- return assert(loadstring(fileStr))()
- end
- end
- end
- return nil
- end
- CETrequire('I2CETableCEA')
- -- I2CETableCEA.autoAssembleFile('CoordHook.CEA', false, false)
- ]====================================================================================================================]--
- local NAME = 'I2 Cheat Engine Table CEA'
- local CLASS_NAME = 'I2CETableCEA'
- local VERSION = '2.1.1'
- local AUTHOR = 'Matt Irwin; Matt.Irwin.US@Gmail.com'
- local LICENSE = [=[MIT License
- Copyright (c) 2017 Matt Irwin
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- ]=]
- local format = string.format
- local strE = string.empty or STRING_EMPTY or ''
- local t = translate
- local default_CEAFilesDirectory = 'ceaFiles'
- local default_AOBSignaturePrivileges = '+X*C*W' -- '+X-C-W'
- local default_CodePrintLines = {
- Before = 7,
- After = 8,
- }
- AOBaddr = nil
- INJaddr = nil
- INJos = 0
- MemRec = nil
- -- memrec = nil
- -- local Logger = {
- -- LEVELS = {
- -- OFF = 0,
- -- FATAL = 1,
- -- ERROR = 2,
- -- WARN = 3,
- -- INFO = 4,
- -- DEBUG = 5,
- -- TRACE = 6
- -- },
- -- }
- -- for k, v in pairs(Logger.LEVELS) do
- -- -- Logger[k:lower()] = function( ... ) return end
- -- -- Logger[k:lower() .. 'f'] = function( ... ) return end
- -- Logger[k:lower()] = function(msg, ex) return print(msg, ex) end
- -- Logger[k:lower() .. 'f'] = function(msg, ... ) return print(string.format(msg, ... )) end
- -- end
- local Logger = Logger
- if Logger == nil then
- if type(CETrequire) == 'function' then
- Logger = CETrequire('I2CETLogger')
- else
- Logger = require('I2CETLogger')
- end
- Logger.LogName = 'I2CETC'
- end
- if type(CETrequire) == 'function' then
- I2CEHelpers = CETrequire('I2CEHelpers')
- else
- I2CEHelpers = require('I2CEHelpers')
- end
- local function split(s, delimiter)
- return I2CEHelpers.split(s, delimiter)
- end
- local function clearGlobals()
- Logger.trace()
- AOBstr = nil
- AOBaddr = nil
- INJaddr = nil
- INJos = 0
- INJbytes = nil
- INJdb = nil
- Logger.debugf('clearGlobals: All %s globals cleared', I2CETableCEA.ClassName)
- end
- I2CETableCEA = {
- Name = NAME,
- ClassName = CLASS_NAME,
- Version = VERSION,
- Author = AUTHOR,
- License = LICENSE,
- CEAFilesDirectory = default_CEAFilesDirectory,
- AOBSignaturePrivileges = default_AOBSignaturePrivileges,
- CodePrintLines = default_CodePrintLines,
- Logger = Logger,
- }
- I2CETableCEA.TableFileInfoSets = {}
- function I2CETableCEA.getPath( ... )
- return I2CEHelpers.getPath( ... )
- end
- function I2CETableCEA.exists(path)
- return I2CEHelpers.exists(path)
- end
- function I2CETableCEA.isFile(path)
- return I2CEHelpers.isFile(path)
- end
- function I2CETableCEA.isDirectory(path)
- return I2CEHelpers.isDirectory(path)
- end
- function I2CETableCEA.reset(prompt)
- Logger.trace()
- local msg = t('Reset I2CETableCEA?')
- local mr = messageDialog(msg, mtConfirmation, mbYes, mbNo, mbCancel)
- if mr == mrYes then
- I2CETableCEA.TableFileInfoSets = {}
- Logger.warn('Table reset.')
- end
- end
- function I2CETableCEA.getFileStr(ceaFile)
- Logger.trace()
- if ceaFile ~= nil then
- Logger.debugf('Loading CEA file: "%s"', ceaFile)
- local localCEAFilePath = ceaFile
- if I2CETableCEA.CEAFilesDirectory ~= nil or I2CETableCEA.CEAFilesDirectory ~= strE then
- localCEAFilePath = I2CETableCEA.getPath(I2CETableCEA.CEAFilesDirectory, ceaFile)
- end
- local fileStr = nil
- local f, err = io.open(localCEAFilePath, 'r')
- if f and not err then
- fileStr = f:read('*all')
- f:close()
- Logger.infof('Returning local file string; "%s"', ceaFile)
- return fileStr
- else
- local tableFile = findTableFile(ceaFile)
- if tableFile == nil then
- Logger.error(format('Error opening table file: "%s"', ceaFile))
- clearGlobals()
- error(format('Error opening table file: "%s"', ceaFile))
- return nil
- end
- local stream = tableFile.getData()
- local fileStr = nil
- local bytes = stream.read(stream.Size)
- for i = 1, #bytes do
- if fileStr == nil then
- fileStr = strE
- end
- fileStr = fileStr .. string.char(bytes[i])
- end
- Logger.infof('Returning table file string; "%s"', ceaFile)
- return fileStr
- end
- end
- return nil
- end
- local function getCodeLines(address)
- Logger.trace()
- if type(address) == 'string' then
- address = tonumber(address, 16)
- end
- local codeStr = disassemble(address) .. ' <<<---- Injection point'
- if type(I2CETableCEA.CodePrintLines) == 'table' then
- if type(I2CETableCEA.CodePrintLines.Before) == 'number'
- and I2CETableCEA.CodePrintLines.Before > 0 then
- local addr = getPreviousOpcode(address)
- for i = 1, I2CETableCEA.CodePrintLines.Before do
- local le = '\r\n'
- if addr == AOBaddr then
- le = ' <<<---- AOB' .. le
- end
- codeStr = disassemble(addr) .. le .. codeStr
- addr = getPreviousOpcode(addr)
- end
- end
- if type(I2CETableCEA.CodePrintLines.After) == 'number'
- and I2CETableCEA.CodePrintLines.After > 0 then
- local addr = address + getInstructionSize(address)
- for i = 1, I2CETableCEA.CodePrintLines.After do
- codeStr = codeStr .. '\r\n' .. disassemble(addr)
- if addr == AOBaddr then
- codeStr = codeStr .. ' <<<---- AOB'
- end
- addr = addr + getInstructionSize(addr)
- end
- end
- end
- return '-------------------- CODE --------------------\r\n'
- .. codeStr .. '\r\n------------------ CODE END ------------------'
- end
- function I2CETableCEA.autoAssembleFile(ceaFile, memrec)
- Logger.trace()
- if type(ceaFile) ~= 'string' then
- local msg = 'Error "ceaFile" must be a string.'
- Logger.error(msg)
- error(msg)
- end
- if memrec == nil then
- local msg = format('Error "memrec" can not be nil; "%s"', ceaFile)
- Logger.error(msg)
- error(msg)
- end
- Logger.debugf('Start: Auto Assemble File: "%s"', ceaFile)
- CEAfile = ceaFile
- MemRec = memrec
- local enable = not memrec.Active
- local fileStr = I2CETableCEA.getFileStr(ceaFile)
- if fileStr then
- Logger.debugf('Assembling File: "%s"', ceaFile)
- if I2CETableCEA.TableFileInfoSets[ceaFile] == nil then
- I2CETableCEA.TableFileInfoSets[ceaFile] = {}
- end
- local assembled = nil
- local disableInfo = I2CETableCEA.TableFileInfoSets[ceaFile].DisableInfo
- local checkOk, errMsg = autoAssembleCheck(fileStr, enable)
- if not checkOk then
- if errMsg == nil or errMsg == strE then
- errMsg = 'No Error Message!'
- end
- Logger.errorf('Syntax error in file: "%s"\r\n%s', ceaFile, errMsg)
- clearGlobals()
- error(format('Syntax error in file: "%s"\r\n%s', ceaFile, errMsg))
- end
- if enable then
- disableInfo = nil
- Logger.infof('ENABLING; "%s"', ceaFile)
- else
- Logger.infof('DISABLING; "%s"', ceaFile)
- end
- assembled, disableInfo = autoAssemble(fileStr, targetSelf, disableInfo)
- if assembled then
- I2CETableCEA.TableFileInfoSets[ceaFile].DisableInfo = disableInfo
- Logger.debugf('File assembled: "%s"', ceaFile)
- clearGlobals()
- Logger.debugf('Done: Auto Assemble File: "%s"', ceaFile)
- return assembled, disableInfo
- else
- Logger.errorf('Error assembling file: "%s"', ceaFile)
- error(format('Error assembling file: "%s"', ceaFile))
- end
- Logger.debugf('Done: Auto Assemble File: "%s"; Error 2', ceaFile)
- return false
- end
- Logger.debugf('Done: Auto Assemble File: "%s"; Error 1', ceaFile)
- return false
- end
- function I2CETableCEA.aobScan(strSignature, aobSignaturePrivileges, ceaFile, index)
- Logger.trace()
- if index == nil then
- index = 0
- end
- local file = ceaFile or CEAfile
- result = AOBScan(strSignature, aobSignaturePrivileges)
- if result == nil then
- local msg = format('Error with "%s", AOB pattern not found: "%s"', file, strSignature)
- Logger.errorf(msg)
- clearGlobals()
- error(msg)
- elseif result.Count >= 1 then
- local aobAddr = result[index]
- result.destroy()
- if type(aobAddr) == 'string' then
- aobAddr = tonumber(aobAddr, 16)
- end
- Logger.infof('AOB scan pattern found at: %016X; "%s"', aobAddr, file)
- return aobAddr
- end
- end
- function I2CETableCEA.reinterpretChildren(memrec)
- local function reintMemrec(memrec)
- for i = 1, memrec.Count - 1 do
- memrec[i].reinterpret()
- if memrec[i].Count > 0 then
- reintMemrec(memrec[i])
- end
- end
- end
- local timer = createTimer(getMainForm())
- timer.Interval = 500
- timer.OnTimer = function(timer)
- reintMemrec(memrec)
- if DoneState == true then
- timer.destroy()
- end
- end
- end
- function I2CETableCEA.getOpcodeAddress(strSignature, offset, aobSignaturePrivileges, ceaFile, index)
- if offset == nil then
- offset = 0
- end
- if type(strSignature) ~= 'string' then
- local msg = 'Error "strSignature" must be a string.'
- Logger.error(msg)
- error(msg)
- end
- if type(offset) ~= 'number' then
- local msg = 'Error "offset" must be a number.'
- Logger.error(msg)
- error(msg)
- end
- local addr = I2CETableCEA.aobScan(strSignature, aobSignaturePrivileges or I2CETableCEA.AOBSignaturePrivileges, ceaFile, index)
- addr = addr + offset
- if targetIs64Bit() then
- local os = readInteger(addr, true)
- return (addr + 4) + os
- else
- return readInteger(addr)
- end
- end
- local function getOpcodeAddress(parameters, syntaxcheck)
- ---- getOpcodeAddress(symbol, aob, (optional) offset, (optional) privileges, (optional) index)
- local tbl = split(parameters, ',')
- local symbol = tbl[1]:gsub(' ', strE)
- local aob = tbl[2]:gsub(' ', strE)
- local offset = tbl[3]
- if offset ~= nil then
- offset = offset:gsub(' ', strE)
- offset = tonumber(offset, 16)
- else
- offset = 0
- end
- local privileges = tbl[4]
- if privileges ~= nil then
- privileges = privileges:gsub(' ', strE)
- end
- local index = tbl[5]
- if index ~= nil then
- index = index:gsub(' ', strE)
- index = tonumber(index, 16)
- else
- index = 0
- end
- if symbol == nil then
- local msg = t('Wrong number of parameters, no "symbol", for "getOpcodeAddress" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if aob == nil then
- local msg = t('Wrong number of parameters, no "aob", for "getOpcodeAddress" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if syntaxcheck then
- return format('define(%s,%016X)', symbol, 0)
- end
- local addr = I2CETableCEA.getOpcodeAddress(aob, offset, privileges or I2CETableCEA.AOBSignaturePrivileges, nil, index)
- return format('define(%s,%016X)', symbol, addr or 0)
- end
- registerAutoAssemblerCommand('getOpcodeAddress', getOpcodeAddress)
- local function setCeaFile(parameters, syntaxcheck)
- ---- setCEAfile(ceaFile)
- ---- setCEAfile(someCeaFile.CEA)
- local ceaFile = parameters
- if ceaFile == nil then
- local msg = t('Wrong number of parameters, no "ceaFile", for "setCEAfile" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end CEAfile = ceaFile
- return strE
- end
- local function getCeaFile(parameters, syntaxcheck)
- ---- getCEAfile()
- return CEAfile
- end
- registerAutoAssemblerCommand('setCEAfile', setCeaFile)
- registerAutoAssemblerCommand('getCEAfile', getCeaFile)
- local function i2AOBscan(parameters, syntaxcheck)
- ---- i2AobScan(symbol, aob, (optional) privileges, (optional) index)
- ---- i2AobScan(injPoint, EBxxxxxxxx90909090)
- ---- i2AobScan(injPoint, EBxxxxxxxx90909090, +X-C*W)
- local tbl = split(parameters, ',')
- local symbol = tbl[1]:gsub(' ', strE)
- local aob = tbl[2]:gsub(' ', strE)
- local privileges = tbl[3]
- if privileges ~= nil then
- privileges = privileges:gsub(' ', strE)
- end
- local index = tbl[4]
- if index ~= nil then
- index = index:gsub(' ', strE)
- index = tonumber(index, 16)
- else
- index = 0
- end
- if symbol == nil then
- local msg = t('Wrong number of parameters, no "symbol", for "i2AobScan" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if aob == nil then
- local msg = t('Wrong number of parameters, no "aob", for "i2AobScan" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if syntaxcheck then
- return format('define(%s,%016X)', symbol, 0)
- end
- local addr = I2CETableCEA.aobScan(aob, privileges or I2CETableCEA.AOBSignaturePrivileges, nil, index)
- return format('define(%s,%016X)', symbol, addr or 0)
- end
- local function i2AOBscanModule(parameters, syntaxcheck)
- ---- i2AobScanModule(symbol, module, aob, (optional) privileges, (optional) index)
- ---- i2AobScanModule(injPoint, game.exe, EBxxxxxxxx90909090)
- ---- i2AobScanModule(injPoint, game.exe, EBxxxxxxxx90909090, +X-C*W)
- local tbl = split(parameters, ',')
- local symbol = tbl[1]:gsub(' ', strE)
- local mod = tbl[2]:gsub(' ', strE)
- local aob = tbl[3]:gsub(' ', strE)
- local privileges = tbl[4]
- if privileges ~= nil then
- privileges = privileges:gsub(' ', strE)
- end
- local index = tbl[4]
- if index ~= nil then
- index = index:gsub(' ', strE)
- index = tonumber(index, 16)
- else
- index = 0
- end
- if symbol == nil then
- local msg = t('Wrong number of parameters, no "symbol", for "i2AobScanModule" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if mod == nil then
- local msg = t('Wrong number of parameters, no "module", for "i2AobScanModule" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if aob == nil then
- local msg = t('Wrong number of parameters, no "aob", for "i2AobScanModule" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if syntaxcheck then
- return format('define(%s,%016X)', symbol, 0)
- end
- local addr = I2CETableCEA.aobScan(aob, privileges or I2CETableCEA.AOBSignaturePrivileges, nil, index)
- return format('define(%s,%016X)', symbol, addr or 0)
- end
- local function i2Assert(parameters, syntaxcheck)
- ---- i2Assert(address, bytes)
- ---- i2Assert(injPoint, 90 90 90 90 90 90)
- ---- i2Assert(injPoint, 909090909090)
- if syntaxcheck then
- return strE
- end
- local tbl = split(parameters, ',')
- local addr = tbl[1]
- local bytes = tbl[2]
- if addr == nil then
- local msg = t('Wrong number of parameters, no "address", for "i2Assert" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if bytes == nil then
- local msg = t('Wrong number of parameters, no "bytes", for "i2Assert" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- addr = getAddressSafe(addr)
- Logger.debugf('Reading from: %016X; "%s"', addr or 0, CEAfile)
- local s = bytes:gsub('%s+', strE)
- local b = {}
- local j = 0
- for i = 1, #s, 2 do
- local n = tonumber(s:sub(i, i + 1), 16)
- b[j] = n
- j = j + 1
- end
- local rb = readBytes(addr, #b + 1, true)
- Logger.infof('Bytes read: %02X; "%s"', #b + 1, CEAfile)
- for i = 0, #b do
- if b[i] ~= rb[i + 1] then
- local s1 = strE
- local s2 = strE
- for x = 0, #b do
- s1 = s1 .. format('%02X', b[x])
- end
- for x = 1, #rb do
- s2 = s2 .. format('%02X', rb[x])
- end
- local msg = format('Error with "%s", bytes don\'t match injection point.', CEAfile)
- Logger.errorf(msg .. '\r\n At: %016X\r\n Got: %s\r\nRead: %s\r\n%s', addr, s1, s2,
- getCodeLines(addr))
- clearGlobals()
- error(msg)
- return nil, msg
- end
- end
- Logger.infof('Bytes matched for: "%s"', CEAfile)
- return strE
- end
- registerAutoAssemblerCommand('i2AobScan', i2AOBscan)
- registerAutoAssemblerCommand('i2AobScanModule', i2AOBscanModule)
- registerAutoAssemblerCommand('i2Assert', i2Assert)
- local function registerLabel(parameters, syntaxcheck)
- ---- registerLabel(name)
- local name = parameters
- if name == nil then
- local msg = t('Wrong number of parameters, no "name", for "registerLabel" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- return format('label(%s)\r\nregisterSymbol(%s)', name, name)
- end
- local function unregisterLabel(parameters, syntaxcheck)
- ---- unregisterLabel(name)
- local name = parameters
- if name == nil then
- local msg = t('Wrong number of parameters, no "name", for "unregisterLabel" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- return format('unregisterSymbol(%s)', name)
- end
- registerAutoAssemblerCommand('registerLabel', registerLabel)
- registerAutoAssemblerCommand('unregisterLabel', unregisterLabel)
- local function defineSymbol(parameters, syntaxcheck)
- ---- defineSymbol(name, value)
- local tbl = split(parameters, ',')
- local name = tbl[1]:gsub(' ', strE)
- local value = tbl[2]
- if name == nil then
- local msg = t('Wrong number of parameters, no "name", for "defineSymbol" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- if value == nil then
- local msg = t('Wrong number of parameters, no "value", for "defineSymbol" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- return format('define(%s,%s)\r\nregisterSymbol(%s)', name, value, name)
- end
- local function undefineSymbol(parameters, syntaxcheck)
- ---- undefineSymbol(name)
- local name = parameters
- if name == nil then
- local msg = t('Wrong number of parameters, no "name", for "undefineSymbol" I2CETableCEA AA command.')
- Logger.error(msg)
- error(msg)
- return nil, msg
- end
- return format('unregisterSymbol(%s)', name)
- end
- registerAutoAssemblerCommand('defineSymbol', defineSymbol)
- registerAutoAssemblerCommand('undefineSymbol', undefineSymbol)
- Logger.debugf('%s: Loaded.', I2CETableCEA.ClassName)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement