--[[ Plugin: AA Maker Version: 2.3.1 Authors: SnedS91, MasterGH По вопросам работы плагина обращаться в тему форума: http://forum.gamehacklab.ru/topic/1415-plugin-aa-maker ]]-- ------------------------------------------------------ local pluginVersion = '2.3.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(->>signatureAddress, ->>arrayOfbyte) alloc(newMem, 2048) label(returnHere) registersymbol(->>signatureAddress) newMem: ->>cheatCode jmp returnHere ->>signatureAddress: jmp newMem ->>nops returnHere: [DISABLE] ->>signatureAddress: ->>originalCode dealloc(newMem) unregistersymbol(->>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, '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 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(mv) 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(mv) 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) 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 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 == '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' 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+Shift+C', OnItemMenuCreateCheatClick, OnSelectionTracker) AddItemMenuInMemoryViewForm('* Get signature info (AA Maker)', 'Ctrl+Shift+I', OnItemMenuGetSignatureInfoClick, OnSelectionTracker)