--[[ CE Lua Plugin: "AA Maker" Version 2.4.1 [EN] Technical support : http://forum.cheatengine.org/viewtopic.php?p=5645967 [RU] Техническая поддержка: http://forum.gamehacklab.ru/topic/1415-plugin-aa-maker-sozdanie-aa-skriptov Authors: SnedS91, MasterGH, ++METHOS Many thanks to "cheatengine.org": Dark Byte, mgr.inz.Player, ++METHOS and all other Many thanks to "Gamehacklab[RU]": Xipho, NullAlex, SER[G]ANT, SnedS91 and all other Our friends: Cheat Engine http://cheatengine.org/ http://forum.cheatengine.org/ Gamehacklab[RU] http://gamehacklab.ru/ Date: 01.02.2016 ]]-- ------------------------------------------------------ local pluginVersion = '2.4.1' SimpleCodeTemplate = [[ [ENABLE] ->>address: ->>cheatCode [DISABLE] ->>address: ->>originalCode ]] AACodeTemplate = [[ [ENABLE] alloc(newMem, 2048) label(returnHere) newMem: ->>cheatCode jmp returnHere ->>address: jmp newMem ->>nops returnHere: [DISABLE] ->>address: ->>originalCode dealloc(newMem) ]] AOBSCANCodeTemplate = [[ [ENABLE] aobscan(aob_->>signatureAddress,->>arrayOfbyte) alloc(newmem_->>signatureAddress,2048) label(returnhere_->>signatureAddress) registersymbol(aob_->>signatureAddress) newmem_->>signatureAddress: ->>cheatCode jmp returnhere_->>signatureAddress aob_->>signatureAddress: jmp newmem_->>signatureAddress ->>nops returnhere_->>signatureAddress: [DISABLE] dealloc(newmem_->>signatureAddress) aob_->>signatureAddress: ->>originalCode unregistersymbol(aob_->>signatureAddress) ]] AOBSCANModuleCodeTemplate = [[ [ENABLE] aobscanmodule(aob_->>signatureAddress,->>address,->>arrayOfbyte) alloc(newmem_->>signatureAddress,2048,->>address) label(originalcode_->>signatureAddress) label(returnhere_->>signatureAddress) registersymbol(aob_->>signatureAddress) //====================================================== newmem_->>signatureAddress: originalcode_->>signatureAddress:->>cheatCode jmp returnhere_->>signatureAddress //->>signatureAddress_enable: //db 0 //====================================================== aob_->>signatureAddress: jmp newmem_->>signatureAddress ->>nops returnhere_->>signatureAddress: [DISABLE] dealloc(newmem_->>signatureAddress) aob_->>signatureAddress: ->>originalCode unregistersymbol(aob_->>signatureAddress) ]] AOBSCANModuleStealthCodeTemplate = [[ [ENABLE] aobscanmodule(aob_->>signatureAddress,->>address,->>arrayOfbyte) alloc(newmem_->>signatureAddress,2048,->>address) stealtheditex(stealth_->>signatureAddress,aob_->>signatureAddress,1) label(originalcode_->>signatureAddress) label(returnhere_->>signatureAddress) label(stealthedit_->>signatureAddress) registersymbol(stealthedit_->>signatureAddress) //====================================================== newmem_->>signatureAddress: originalcode_->>signatureAddress:->>cheatCode jmp returnhere_->>signatureAddress //->>signatureAddress_enable: //db 0 //====================================================== stealth_->>signatureAddress: stealthedit_->>signatureAddress: jmp newmem_->>signatureAddress ->>nops returnhere_->>signatureAddress: [DISABLE] dealloc(newmem_->>signatureAddress) stealthedit_->>signatureAddress: ->>originalCode unregistersymbol(stealthedit_->>signatureAddress) ]] ------------------------------------------------------ PATTERN = { ['inc'] = 'mov->>type[x],->>value', ['mov'] = 'mov->>type[x],->>value\r\n->>originalCode', ['fld'] = 'mov->>type[x],->>value\r\n->>originalCode', ['fstp'] = '->>originalCode\r\nmov->>type[x],->>value' } ------CODE--SECTION----------------------------------- local captionForm = 'AA Maker '.. pluginVersion local scriptName = '' local cheatType = '' local cheatName = '' local cheatValueType = '' local patternInjectAsmCode = '' local cheatCode = '' local originalCode = '' local originalBytes = '' local nops = '' local strSignature = '' local cheatValue = 0 local testBytes = 0 local origCodeType = 0 scriptCount = 0 ------------------------------------------------------ local form = createForm(false) form_centerScreen(form) control_setSize(form, 181,223) component_setName(form,'fmAdvCheat') control_setCaption(form, captionForm) setProperty(form,'BorderIcons','[biSystemMenu]') form_onClose(form, form_hide(form)) local edCheatName = createEdit(form) control_setSize(edCheatName, 168,23) control_setPosition(edCheatName, 7,19) setProperty(edCheatName,'Name','edCheatName') setProperty(edCheatName,'Text','') local labelCheatName = createLabel(form) control_setPosition(labelCheatName, 16,2) control_setCaption(labelCheatName,'Cheat name [optional]:') local groupBox = createGroupBox(form) control_setSize(groupBox, 172,96) control_setPosition(groupBox, 4,45) control_setCaption(groupBox,'Cheat type') local cmbCheatType = createComboBox(groupBox) component_setName(cmbCheatType,'cmbCheatType') control_setSize(cmbCheatType, 160,23) control_setPosition(cmbCheatType, 4,1) local items = combobox_getItems(cmbCheatType) strings_add(items, 'Simple') strings_add(items, 'Injection') strings_add(items, 'Nops') strings_add(items, 'AOBScan') strings_add(items, 'AOBScanModule') strings_add(items, 'AOBScanModuleStealth') strings_add(items, 'Disable CALL') setProperty(cmbCheatType, 'ReadOnly', true) combobox_setItemIndex(cmbCheatType,0) local cbTestingBytes = createCheckBox(groupBox) component_setName(cbTestingBytes,'cbTestingBytes') control_setSize(cbTestingBytes, 90,19) control_setPosition(cbTestingBytes, 3,30) control_setCaption(cbTestingBytes,'Testing bytes') control_setEnabled(cbTestingBytes, false) local cbOrigCodeType = createCheckBox(groupBox) component_setName(cbOrigCodeType,'cbOrigCodeType') control_setSize(cbOrigCodeType, 135,19) control_setPosition(cbOrigCodeType, 3,54) control_setCaption(cbOrigCodeType,'Original code in bytes') local edValue = createEdit(form) control_setSize(edValue, 68,23) control_setPosition(edValue, 7,166) setProperty(edValue,'Name','edValue') setProperty(edValue,'Text','100') local labelValue = createLabel(form) control_setPosition(labelValue, 7,146) control_setCaption(labelValue,'Value:') local cmbType = createComboBox(form) component_setName(cmbType,'cmbType') control_setSize(cmbType, 96,23) control_setPosition(cmbType, 77,166) setProperty(cmbType, 'ReadOnly', true) local typevalitems = combobox_getItems(cmbType) strings_add(typevalitems, 'hexadecimal') strings_add(typevalitems, 'decimal') strings_add(typevalitems, 'float') combobox_setItemIndex(cmbType,1) local labelTypeValue = createLabel(form) control_setPosition(labelTypeValue, 77,146) control_setCaption(labelTypeValue,'Type of value:') local btnOk = createButton(form) component_setName(btnOk,'btnOk') control_setCaption(btnOk,'Create Script') control_setSize(btnOk, 176,24) control_setPosition(btnOk, 3,195) setProperty(btnOk, 'Default', true) ------------------------------------------------------ function checkPattern() local address = getNameFromAddress(dv_address1) local _,opcode = splitDisassembledString(disassemble(address)) local choose = getProperty(cmbCheatType,"Text") if choose == 'Injection' or choose == 'AOBScan' then for key,value in pairs(PATTERN) do if string.find(opcode,key) ~= nil then local _,_,x = string.find(opcode, '%[(.*)%]') if x ~= nil then patternInjectAsmCode = value return true end end end end patternInjectAsmCode = '->>originalCode' return false end function getCheatCode(address, value, valyeType) local _,opcode = splitDisassembledString(disassemble(address)) opcode = getAddressFromOpcode(opcode) local newCode = '' local opType = ' ' if checkPattern() then if string.find(opcode, " .* ptr ") ~= nil then opType = string.sub(opcode, string.find(opcode, ' .* ptr ')) end local _,_,x = string.find(opcode, '%[(.*)%]') if x ~= nil then newCode = string.gsub(patternInjectAsmCode,'->>type',opType) newCode = string.gsub(newCode,'%[x%]','['..x..']') newCode = string.gsub(newCode,'->>value',valyeType..value) if string.find(opcode, '%],') ~= nil then if string.find(originalCode, '^.*\r?\n') ~= nil then newCode = string.gsub(newCode,'->>originalCode',originalCode:gsub('^.*\r?\n','')) else newCode = string.gsub(newCode,'\r?\n*->>originalCode','') end else newCode = string.gsub(newCode,'->>originalCode',originalCode) end end else newCode = '\r\n'..originalCode end return newCode end function getOriginalCodeString(strAddress, length, typeNops) local sumBytes = 0 local nopsCount = 0 local originalCodeString = '' local originalBytesString = '' local nopsString = '' local address = strAddress repeat local InstructionSize = getInstructionSize(address) _,opcode,bytes,address = splitDisassembledString(disassemble(address)) opcode = getAddressFromOpcode(opcode) sumBytes = sumBytes + InstructionSize address = address..'+'..InstructionSize _,_,_,address = splitDisassembledString(disassemble(address)) if sumBytes >= length then originalCodeString = originalCodeString..opcode else originalCodeString = originalCodeString..opcode..'\r\n' end originalBytesString = originalBytesString..bytes until (sumBytes >= length) if typeNops then nopsCount = sumBytes - length else nopsCount = length end if nopsCount > 0 then if nopsCount < 3 then for i = 1, nopsCount do if i == nopsCount then nopsString = nopsString.."nop" else nopsString = nopsString.."nop\r\n" end end else nopsString = 'db ' for i = 1, nopsCount do if i == nopsCount then nopsString = nopsString.."90" else nopsString = nopsString.."90 " end end end end originalBytesString = 'db'..string.gsub(originalBytesString:gsub(' ',''),'(%x)(%x)',' %1%2') return originalCodeString, nopsString, originalBytesString end function getAddressFromOpcode(opcode) local strRet = '' local namedAddr = '' local base = '' local offset = '' for addr in string.gmatch(opcode, "%x+") do if addr ~= nil and #addr > 5 then namedAddr = getNameFromAddress(addr) if namedAddr == addr then strRet = opcode else offset = string.match(namedAddr, "%x+$") base = string.gsub(namedAddr, "+"..offset, "") if string.find(base, "%s") ~= nil then strRet = string.gsub(opcode,addr,"\"" .. base .. "\"+" .. offset) else strRet = string.gsub(opcode,addr,base .. "+" .. offset) end end else strRet = opcode end end if strRet == '' then strRet = opcode end return strRet end function getReturnFromCall(strAddress) local address = strAddress local retnStr = '' local _,opcode = splitDisassembledString(disassemble(address)) if string.match(opcode, "%a+") ~= 'call' then messageDialog("This isn't CALL-function!\r\nPlease choose another instruction!",mtWarning,mbOK) return false end address = string.match(opcode, "%x+") if address ~= nil then if (string.find(opcode, "%x+%p$") ~= nil) then address = string.format('%X',readInteger(address)) end local _address = address repeat local countBytes = getInstructionSize(_address) _address = _address..'+'..countBytes _,opcode,_,_address = splitDisassembledString(disassemble(_address)) local currentInstr = string.match(opcode, "%a+") if currentInstr == 'ret' then retnStr = opcode end until (retnStr ~= '') local sizeRet = getInstructionSize(_address) originalCode, nops, originalBytes = getOriginalCodeString(address, sizeRet, true) cheatCode = retnStr..'\r\n'..nops return true,address else messageDialog("Address not found!\r\nPlease choose another instruction!",mtWarning,mbOK) return false end end function getFullSignature(startAddress, stopAddress) local addr = startAddress local stop = stopAddress local str = '' local _str = '' local count = -1 local result = '' local num = 2 local minNum = 4 if testBytes then num = 8 minNum = 12 end str,addr = getBytesForAOB(addr, stop, stop) if #str > minNum then result = AOBScan(str, '+X-C-W') count = strings_getCount(result) object_destroy(result) end while count ~= 1 do str = str.._str _str,addr = getBytesForAOB(addr, num) result = AOBScan(str.._str, '+X-C-W') count = strings_getCount(result) object_destroy(result) end while count ~= 1 do str = str.._str _str,addr = getBytesForAOB(addr, num) result = AOBScanModule(str.._str, '+X-C-W') count = strings_getCount(result) object_destroy(result) end while count ~= 1 do str = str.._str _str,addr = getBytesForAOB(addr, num) result = AOBScanModule(str.._str, '+X-C-W') count = strings_getCount(result) object_destroy(result) end local numOflast = #string.gsub(_str,'x','')/2 while (numOflast > 1) do local nL = math.floor(numOflast/2) local nR = numOflast - nL local _strL, _strR if testBytes then _strL = string.match(_str,string.rep('x*%x+x+',nL)) _strR = string.match(_str,string.rep('%x+x*',nR),#_strL) else _strL = string.sub(_str,1,2*nL) _strR = string.sub(_str,2*nL+1) end if strings_getCount(AOBScan(str.._strL, '+X-C-W')) == 1 then _str = _strL numOflast = nL else str = str.._strL _str = _strR numOflast = nR end end str = str.._str if testBytes then str = string.lower(str) else str = str:gsub('(.)(.)', '%1%2 ') end str = str:gsub('x*%s*$','') return str end function getBytesForAOB(startAddress, num, stop) local addr = startAddress local str = '' for i = 1,num do local sizeInstruction = getInstructionSize(addr) local _,_,bytes = splitDisassembledString(disassemble(addr)) local fstBt, othBt = string.match(bytes,'^%x+'),string.match(bytes,' .+$') if testBytes then if othBt ~= nil then othBt = string.gsub(string.gsub(othBt,'%s',''),'%x','x') str = str..fstBt..othBt else str = str..string.gsub(fstBt,'%x','x') end else str = str..string.gsub(bytes,'%s','') end if addr == stop then addr = addr + sizeInstruction break end addr = addr + sizeInstruction end return str,addr end ------------------------------------------------------ function AddAARecord(script, sciptName) local addresslist = getAddressList() newTableEntry = addresslist_createMemoryRecord(addresslist) memoryrecord_setDescription(newTableEntry, sciptName) memoryrecord_setType(newTableEntry, vtAutoAssembler) memoryrecord_setScript(newTableEntry, script) return newTableEntry end function OpenAAEditor(newTableEntry) local addresslist = getAddressList() addresslist_setSelectedRecord(addresslist, newTableEntry) addresslist_doValueChange(addresslist) end -------Add Item Menu in Disassembler------------------ function OnSelectionTracker(disassemblerview, address, address2) dv_address1=address dv_address2=address2 if checkPattern() then control_setEnabled(edValue, true) control_setEnabled(cmbType, true) else control_setEnabled(edValue, false) control_setEnabled(cmbType, false) end end function AddItemMenuInMemoryViewForm(nameItemMenu, shortcut, functionItemClick, functionSelectiontracker) local mv = getMemoryViewForm() local dv = memoryview_getDisassemblerView(mv) disassemblerview_onSelectionChange(dv, functionSelectiontracker) dv_address1 = disassemblerview_getSelectedAddress(dv) dv_address2 = dv_address1 popupmenu = control_getPopupMenu(dv) mi = createMenuItem(popupmenu) menuItem_setCaption(mi, nameItemMenu) menuItem_onClick(mi, functionItemClick) menuItem_setShortcut(mi, shortcut) menuItem_add(menu_getItems(popupmenu), mi) end function AddItemMenu(menuItem, nameItemMenu, shortcut, functionItemClick) local mi = createMenuItem(popupmenu) menuItem_setCaption(mi, nameItemMenu) menuItem_setShortcut(mi, shortcut) menuItem_onClick(mi, functionItemClick) menuItem_add(menuItem, mi) end function AddItemWithSubMenusInMemoryViewForm(nameItemMenu, functionSelectiontracker) local mv = getMemoryViewForm() local dv = memoryview_getDisassemblerView(mv) disassemblerview_onSelectionChange(dv, functionSelectiontracker) dv_address1 = disassemblerview_getSelectedAddress(dv) dv_address2 = dv_address1 popupmenu = control_getPopupMenu(dv) mmenu_items = menu_getItems(popupmenu) mi = createMenuItem(popupmenu) menuItem_setCaption(mi, nameItemMenu) menuItem_add(menu_getItems(popupmenu), mi) AddItemMenu(mi, 'Create AA Simple', 'Ctrl+1', OnGenerateAASimpleClick) AddItemMenu(mi, 'Create AA Injection', 'Ctrl+2', OnGenerateAAInjectionClick) AddItemMenu(mi, 'Create AA Nop', 'Ctrl+3', OnGenerateAANopClick) AddItemMenu(mi, 'Create AA AOBScan', 'Ctrl+4', OnGenerateAAAobScanClick) AddItemMenu(mi, 'Disable CALL', 'Ctrl+5', OnGenerateAADisableCallClick) AddItemMenu(mi, 'Create AA AOBScanModule', 'Ctrl+6', OnGenerateAAAobScanModuleClick) AddItemMenu(mi, 'Create AA AOBScanModuleStealth', 'Ctrl+7', OnGenerateAAAobScanModuleStealthClick) end function AddItemMenuSeparatorInMemoryViewForm() local mv = getMemoryViewForm() local dv = memoryview_getDisassemblerView(mv) disassemblerview_onSelectionChange(dv, functionSelectiontracker) popupmenu = control_getPopupMenu(dv) mi = createMenuItem(popupmenu) menuItem_setCaption(mi, '-') menuItem_add(menu_getItems(popupmenu), mi) end ------------------------------------------------------ function generateAA(typeofcheat) setProperty(cmbCheatType,"Text", typeofcheat) cmbCheatTypeChange() btnOkClick() end function OnItemMenuCreateCheatClick(sender) form_show(form) end function OnGenerateAASimpleClick(sender) generateAA('Simple') end function OnGenerateAAInjectionClick(sender) generateAA('Injection') end function OnGenerateAANopClick(sender) generateAA('Nops') end function OnGenerateAAAobScanClick(sender) generateAA('AOBScan') end function OnGenerateAADisableCallClick(sender) generateAA('Disable CALL') end function OnGenerateAAAobScanModuleClick(sender) generateAA('AOBScanModule') end function OnGenerateAAAobScanModuleStealthClick(sender) generateAA('AOBScanModuleStealth') end function OnItemMenuGetSignatureInfoClick(sender) print('--START--') local address = math.min(dv_address1, dv_address2) print('Address: '..getNameFromAddress(address)..' or '.. string.format('%08x', address)) local stop = math.max(dv_address1, dv_address2) local length = stop + getInstructionSize(stop) - address local bytestring = readBytes(address, length, true) local strSignature = '' local result local count = -1 a2 = getPreviousOpcode(address) a1 = getPreviousOpcode(a2) a4 = address + getInstructionSize(address) a5 = a4 + getInstructionSize(a4) print('') print('Original view code:') print(' ' .. disassemble(a1)) print(' ' .. disassemble(a2)) print(' ' .. disassemble(address) .. '<<<') print(' ' .. disassemble(a4)) print(' ' .. disassemble(a5)) print('') if length <= 5 then print('Sorry. You must selected more 5 bytes') return end for i=1, length do strSignature=strSignature..string.format('%02X ', bytestring[i]) end print('Start AOBScan with : '.. strSignature) result = AOBScan(strSignature, '+X-C-W') if result == nil then print(' ' ..'Sorry. Attention, not find signature! Check it out yourself! :(') else count = strings_getCount(result) object_destroy(result) print('') if (count == 1) then print(' ' ..'Signature is unique. Yes, is good! :) ') else print(' ' ..string.format('Sorry. Signature is not unique. :( Found addresses = %s', count)) end print('') strSignature = getBytesForAOB(address,length,stop) print('Testing bytes string : ' .. strSignature) print('') end print('Thank you for using this lua-plagin, GameHackLab[RU], 2009-2013(C)') print('--END--') end ------------------------------------------------------ function btnOkClick() local script = '' local address = math.min(dv_address1, dv_address2) local stop = math.max(dv_address1, dv_address2) local length = stop + getInstructionSize(stop) - address cheatType = getProperty(cmbCheatType,"Text") cheatName = getProperty(edCheatName,"Text") cheatValue = getProperty(edValue,"Text") cheatValueType = getProperty(cmbType,"Text") testBytes = getProperty(cbTestingBytes,"Checked") origCodeType = getProperty(cbOrigCodeType,"Checked") if cheatValueType == 'decimal' then cheatValueType = '#' elseif cheatValueType == 'float' then cheatValueType = '(float)' else cheatValueType = '' end if cheatType == 'Simple' then script = SimpleCodeTemplate originalCode,_,originalBytes = getOriginalCodeString(address, length) cheatCode = originalCode elseif cheatType == 'Injection' then script = AACodeTemplate originalCode, nops, originalBytes = getOriginalCodeString(address, 5, true) cheatCode = getCheatCode(address, cheatValue,cheatValueType) elseif cheatType == 'Nops' then script = SimpleCodeTemplate originalCode,cheatCode,originalBytes = getOriginalCodeString(address, length) elseif cheatType == 'AOBScan' then script = AOBSCANCodeTemplate strSignature = getFullSignature(address, stop) originalCode, nops, originalBytes = getOriginalCodeString(address, 5, true) cheatCode = getCheatCode(address, cheatValue,cheatValueType) elseif cheatType == 'AOBScanModule' then script = AOBSCANModuleCodeTemplate strSignature = getFullSignature(address, stop) originalCode, nops, originalBytes = getOriginalCodeString(address, 5, true) cheatCode = getCheatCode(address, cheatValue,cheatValueType) elseif cheatType == 'AOBScanModuleStealth' then script = AOBSCANModuleStealthCodeTemplate strSignature = getFullSignature(address, stop) originalCode, nops, originalBytes = getOriginalCodeString(address, 5, true) cheatCode = getCheatCode(address, cheatValue,cheatValueType) elseif cheatType == 'Disable CALL' then local ret = false script = SimpleCodeTemplate ret,address = getReturnFromCall(address) if ret == false then script = '' end end if script ~= '' then script = string.gsub(script,"->>arrayOfbyte", strSignature) script = string.gsub(script,"->>address", getNameFromAddress(address)) script = string.gsub(script,"->>cheatCode", cheatCode) script = string.gsub(script,"->>NscriptCount", scriptCount) if origCodeType == true then script = string.gsub(script,"->>originalCode", originalBytes) else script = string.gsub(script,"->>originalCode", originalCode) end if nops ~= '' then script = string.gsub(script,"->>nops", nops) else script = string.gsub(script,'\n?->>nops', '') end if cheatName ~= '' then scriptName = cheatName if string.find(cheatName, '^%d') ~= nil then cheatName = '_'..cheatName end else scriptName = 'New Script '..scriptCount cheatName = 'address'..scriptCount scriptCount = scriptCount + 1 end script = string.gsub(script,"->>signatureAddress", cheatName) local newTableEntry = AddAARecord(script,scriptName) OpenAAEditor(newTableEntry) end form_hide(form) end function cmbCheatTypeChange(sender) cheatType = getProperty(cmbCheatType,"Text") if cheatType == 'Nops' or cheatType == 'Disable CALL' then control_setEnabled(edValue, false) control_setEnabled(cmbType, false) else if checkPattern() then control_setEnabled(edValue, true) control_setEnabled(cmbType, true) end end if cheatType == 'AOBScan' or cheatType == 'AOBScanModule' or cheatType == 'AOBScanModuleStealth' then control_setEnabled(cbTestingBytes, true) else control_setEnabled(cbTestingBytes, false) end end function cbTestingBytesChange(sender) ------------------- end ------------------------------------------------------ setMethodProperty(cmbCheatType, 'OnChange', cmbCheatTypeChange) --setMethodProperty(cbTestingBytes, 'OnChange', cbTestingBytesChange) btnOk:setOnClick(btnOkClick) ------------------------------------------------------ AddItemMenuSeparatorInMemoryViewForm() AddItemWithSubMenusInMemoryViewForm('* Quick AA Maker', OnSelectionTracker) AddItemMenuInMemoryViewForm('* AA Maker Window', 'Ctrl+Z', OnItemMenuCreateCheatClick, OnSelectionTracker) AddItemMenuInMemoryViewForm('* Get signature info (AA Maker)', 'Ctrl+Shift+I', OnItemMenuGetSignatureInfoClick, OnSelectionTracker)