if cheatEngineIs64Bit() then --Initialization------------------------------------------------------------------------------------ local INITIALIZATION_INJECT = createStringlist() INITIALIZATION_INJECT.Text = [==[ //**********Initialization************************************************************************// aobscanmodule(deleteHotkey_searchedAOB,cheatengine-x86_64.exe,48 8B 48 38 E8 * * * * 48 8B 8B * * * * E8 * * * * 48 89 C1 E8 * * * * 66 90 90) aobscanmodule(editHotkey_searchedAOB1,cheatengine-x86_64.exe,48 8B 83 * * * * 48 89 46 * 66 8B 83) aobscanmodule(editHotkey_searchedAOB2,cheatengine-x86_64.exe,48 8B 55 * 48 8D 4E * E8 * * * * 48 8B 8B * * * * 48 8D * * E8 * * * * 48 * * * 48 * * * E8 * * * * 48 * * E8) aobscanmodule(addHotkey_searchedAOB,cheatengine-x86_64.exe,49 89 F9 E8 * * * * 48 89 C6) registersymbol(deleteHotkey_searchedAOB) registersymbol(editHotkey_searchedAOB1) registersymbol(editHotkey_searchedAOB2) registersymbol(addHotkey_searchedAOB) aobscanmodule(isSelected_searchedAOB,cheatengine-x86_64.exe,C6 80 * * * * 01 48 8B 8B * * * * E8 * * * * 48 * * E8) aobscanmodule(HotkeyListOffset_searchedAOB,cheatengine-x86_64.exe,C7 40 * FF FF FF FF 48 8B 45 * 48 8B 55 * 48 89 50 * 48 8B 45 * 48 8B 40) registersymbol(isSelected_searchedAOB) registersymbol(HotkeyListOffset_searchedAOB) ]==] autoAssemble(INITIALIZATION_INJECT.Text,true) --Libary Functions---------------------------------------------------------------------------------- --Local Functions Declaration local convertUIntToInt function convertUIntToInt(int) if (int >> 31) == 1 then return int - math.floor(2^32) end return int end --Main---------------------------------------------------------------------------------------------- local MAIN_INJECT = createStringlist() MAIN_INJECT.Text = [==[ //**********Shared Resources**********************************************************************// alloc(rax_bak,8) alloc(rbx_bak,8) alloc(rcx_bak,8) alloc(rdx_bak,8) alloc(r8_bak,8) alloc(r9_bak,8) alloc(r10_bak,8) alloc(r11_bak,8) alloc(rsp_plus_20_bak,8) alloc(TAddressList,8) alloc(selectedMemoryRecordAddress,8) alloc(selectedHotkeyAddress,8) alloc(selectedHotkeyIndex,8) alloc(loopIndex,8) alloc(loopCount,8) alloc(loopArray,$1000) //registersymbol(rax_bak) //registersymbol(rbx_bak) //registersymbol(rcx_bak) //registersymbol(rdx_bak) //registersymbol(r8_bak) //registersymbol(r9_bak) //registersymbol(r10_bak) //registersymbol(r11_bak) //registersymbol(rsp_plus_20_bak) //registersymbol(TAddressList) //registersymbol(selectedMemoryRecordAddress) //registersymbol(selectedHotkeyAddress) //registersymbol(selectedHotkeyIndex) //registersymbol(loopIndex) //registersymbol(loopCount) //registersymbol(loopArray) loopIndex: dd 00 loopCount: dd 00 loopArray: dd 00 TAddressList: %REPLACE1% alloc(libraryFunc_newmem,$1000,"cheatengine-x86_64.exe") label(getListViewSelectedIndex) label(getListViewSelectedIndex_loop) label(getListViewSelectedIndex_break) label(getSelectedRecordsHotkey) label(getSelectedRecordsHotkey_loop) label(getSelectedRecordsHotkey_nextChild_continue) label(getSelectedRecordsHotkey_nextElement_continue) label(getSelectedRecordsHotkey_exit) label(getSelectedRecords) label(getSelectedRecords_loop) label(getSelectedRecords_nextChild_continue) label(getSelectedRecords_nextElement_continue) label(getSelectedRecords_exit) //registersymbol(libraryFunc_newmem) //registersymbol(getListViewSelectedIndex) //registersymbol(getListViewSelectedIndex_loop) //registersymbol(getListViewSelectedIndex_break) //registersymbol(getSelectedRecordsHotkey) //registersymbol(getSelectedRecordsHotkey_loop) //registersymbol(getSelectedRecordsHotkey_nextChild_continue) //registersymbol(getSelectedRecordsHotkey_nextElement_continue) //registersymbol(getSelectedRecordsHotkey_exit) //registersymbol(getSelectedRecords) //registersymbol(getSelectedRecords_loop) //registersymbol(getSelectedRecords_nextChild_continue) //registersymbol(getSelectedRecords_nextElement_continue) //registersymbol(getSelectedRecords_exit) libraryFunc_newmem: getListViewSelectedIndex: mov r8,[selectedHotkeyAddress] //mov rax,[rbx+848] //Selected.TMemoryRecord %REPLACE6% mov [selectedMemoryRecordAddress],rax //mov rax,[rax+48] %REPLACE8% mov rax,[rax+8] mov ebx,[rax+10] //sizeof(TMemoryRecord.Hotkey[]) mov rax,[rax+8] //TMemoryRecord.Hotkey[] xor rcx,rcx getListViewSelectedIndex_loop: //Loop through Hotkey[] n times, not more then sizeof(Hotkey[]) cmp rcx,rbx jae short getListViewSelectedIndex_break mov rdx,[rax+rcx*8] add rcx,#1 cmp r8,rdx jne short getListViewSelectedIndex_loop getListViewSelectedIndex_break: mov [selectedHotkeyIndex],rcx ret getSelectedRecordsHotkey: mov rax,[TAddressList] //TAddressList lea rax,[rax+F50-48] //TMemoryRecord[] getSelectedRecordsHotkey_loop: mov rax,[rax+48] //TMemoryRecord[i] Next Linked List Element mov rbx,[rax+28] //TMemoryRecord cmp rbx,[selectedMemoryRecordAddress] //Check if is selected memory record je short getSelectedRecordsHotkey_nextChild_continue //cmp byte ptr [rbx+180],#1 //TMemoryRecord.isSelected type:boolean %REPLACE7% jne short getSelectedRecordsHotkey_nextChild_continue //mov rbx,[rbx+48] %REPLACE9% mov rbx,[rbx+8] mov ecx,[rbx+10] //sizeof(TMemoryRecord.Hotkey[]) mov rdx,[selectedHotkeyIndex] cmp rcx,rdx jb short getSelectedRecordsHotkey_nextChild_continue //Skips if memory record has less hotkeys than the selected index sub rdx,#1 mov rbx,[rbx+8] //TMemoryRecord.Hotkey[] mov rbx,[rbx+rdx*8] //TMemoryRecord.Hotkey mov rcx,[loopCount] mov [loopArray+rcx*8],rbx add [loopCount],#1 getSelectedRecordsHotkey_nextChild_continue: cmp dword ptr [rax+24],#0 //Check if has child records je short getSelectedRecordsHotkey_nextElement_continue mov rax,[rax+40] mov rax,[rax] //Get first child TMemoryRecord[] Element jmp getSelectedRecordsHotkey_loop+4 getSelectedRecordsHotkey_nextElement_continue: cmp [rax+48],#0 //Check if next element is valid jne short getSelectedRecordsHotkey_loop cmp [rax+60],#0 //Check if has parent record je short getSelectedRecordsHotkey_exit mov rax,[rax+60] //Return to parent record jmp getSelectedRecordsHotkey_nextElement_continue getSelectedRecordsHotkey_exit: ret getSelectedRecords: mov rax,[TAddressList] //TAddressList lea rax,[rax+F50-48] //TMemoryRecord[] getSelectedRecords_loop: mov rax,[rax+48] //TMemoryRecord[i] Next Linked List Element mov rbx,[rax+28] //TMemoryRecord cmp rbx,[rcx_bak] //Check if is primary selected memory record je short getSelectedRecords_nextChild_continue //cmp byte ptr [rbx+180],#1 //TMemoryRecord.isSelected type:boolean %REPLACE7% jne short getSelectedRecords_nextChild_continue mov rcx,[loopCount] mov [loopArray+rcx*8],rbx add [loopCount],#1 getSelectedRecords_nextChild_continue: cmp dword ptr [rax+24],#0 //Check if has child records je short getSelectedRecords_nextElement_continue mov rax,[rax+40] mov rax,[rax] //Get first child TMemoryRecord[] Element jmp getSelectedRecords_loop+4 getSelectedRecords_nextElement_continue: cmp [rax+48],#0 //Check if next element is valid jne short getSelectedRecords_loop cmp [rax+60],#0 //Check if has parent record je short getSelectedRecords_exit mov rax,[rax+60] //Return to parent record jmp getSelectedRecords_nextElement_continue getSelectedRecords_exit: ret //**********deleteHotkey**************************************************************************// alloc(deleteHotkey_newmem,$1000,deleteHotkey_searchedAOB) label(deleteHotkey_loop) label(deleteHotkey_originalcode) label(deleteHotkey_return) //registersymbol(deleteHotkey_newmem) //registersymbol(deleteHotkey_loop) //registersymbol(deleteHotkey_originalcode) //registersymbol(deleteHotkey_return) deleteHotkey_newmem: //Reset loop counters mov [loopIndex],#0 mov [loopCount],#0 //Backup registers mov [rax_bak],rax mov [rbx_bak],rbx mov [rcx_bak],rcx mov [rdx_bak],rdx mov [r8_bak],r8 mov [r9_bak],r9 mov [r10_bak],r10 mov [r11_bak],r11 mov [selectedHotkeyAddress],rcx call getListViewSelectedIndex call getSelectedRecordsHotkey //Add Original HotkeyRecord (RAX/RCX) to loopArray mov rcx,[loopCount] push rax mov rax,[rcx_bak] mov [loopArray+rcx*8],rax pop rax add [loopCount],#1 deleteHotkey_loop: //Get selected memory record hotkey addresses mov rax,[loopIndex] mov rcx,[loopArray+rax*8] mov rax,rcx add [loopIndex],#1 //Restore registers mov rbx,[rbx_bak] mov rdx,[rdx_bak] mov r8,[r8_bak] mov r9,[r9_bak] mov r10,[r10_bak] mov r11,[r11_bak] //call cheatengine-x86_64.exe+107A0 //Original Code %REPLACE2% push rax mov rax,[loopIndex] cmp rax,[loopCount] pop rax jb short deleteHotkey_loop deleteHotkey_originalcode: jmp deleteHotkey_return deleteHotkey_searchedAOB+4: jmp deleteHotkey_newmem deleteHotkey_return: //**********editHotkey****************************************************************************// //**********editHotkey Start**********// alloc(editHotkey_newmem1,$1000,editHotkey_searchedAOB1) label(editHotkey_loop) label(editHotkey_originalcode1) label(editHotkey_return1) registersymbol(editHotkey_newmem1) registersymbol(editHotkey_loop) registersymbol(editHotkey_originalcode1) registersymbol(editHotkey_return1) editHotkey_newmem1: //Reset loop counters mov [loopIndex],#0 mov [loopCount],#0 //Backup registers mov [rax_bak],rax mov [rbx_bak],rbx mov [rcx_bak],rcx mov [rdx_bak],rdx mov [r8_bak],r8 mov [r9_bak],r9 mov [r10_bak],r10 mov [r11_bak],r11 mov [selectedHotkeyAddress],rsi call getListViewSelectedIndex call getSelectedRecordsHotkey //Add Original HotkeyRecord (RSI) to loopArray mov rcx,[loopCount] mov [loopArray+rcx*8],rsi add [loopCount],#1 editHotkey_loop: //Get selected memory record hotkey addresses mov rax,[loopIndex] mov rsi,[loopArray+rax*8] add [loopIndex],#1 //Restore registers mov rax,[rax_bak] mov rbx,[rbx_bak] mov rcx,[rcx_bak] mov rdx,[rdx_bak] mov r8,[r8_bak] mov r9,[r9_bak] mov r10,[r10_bak] mov r11,[r11_bak] editHotkey_originalcode1: //mov rax,[rbx+00000850] %REPLACE5% jmp editHotkey_return1 editHotkey_searchedAOB1: jmp editHotkey_newmem1 nop nop editHotkey_return1: //**********editHotkey End**********// alloc(editHotkey_newmem2,$1000,editHotkey_searchedAOB2) label(editHotkey_originalcode2) label(editHotkey_return2) registersymbol(editHotkey_newmem2) registersymbol(editHotkey_originalcode2) registersymbol(editHotkey_return2) editHotkey_newmem2: //call cheatengine-x86_64.exe+AFE0 //Original Code %REPLACE3% push rax mov rax,[loopIndex] cmp rax,[loopCount] pop rax jb editHotkey_loop editHotkey_originalcode2: jmp editHotkey_return2 editHotkey_searchedAOB2+8: jmp editHotkey_newmem2 editHotkey_return2: //**********addHotkey*****************************************************************************// alloc(addHotkey_newmem,$1000,addHotkey_searchedAOB) label(addHotkey_loop) label(addHotkey_originalcode) label(addHotkey_return) registersymbol(addHotkey_newmem) registersymbol(addHotkey_loop) registersymbol(addHotkey_originalcode) registersymbol(addHotkey_return) addHotkey_newmem: //Reset loop counters mov [loopIndex],#0 mov [loopCount],#0 //Backup registers mov [rax_bak],rax mov [rbx_bak],rbx mov [rcx_bak],rcx mov [rdx_bak],rdx mov [r8_bak],r8 mov [r9_bak],r9 mov [r10_bak],r10 mov [r11_bak],r11 mov rax,[rsp+20] mov [rsp_plus_20_bak],rax call getSelectedRecords cmp [loopCount],0 //Skips if only one selected memory record je short addHotkey_originalcode addHotkey_loop: //Get selected memory record addresses mov rax,[loopIndex] mov rcx,[loopArray+rax*8] add [loopIndex],1 //Restore registers mov rax,[rsp_plus_20_bak] mov [rsp+20],rax mov rax,[rax_bak] mov rbx,[rbx_bak] mov rdx,[rdx_bak] mov r8,[r8_bak] mov r9,[r9_bak] mov r10,[r10_bak] mov r11,[r11_bak] //call cheatengine-x86_64.exe+1BF540 //Original Code %REPLACE4% mov rax,[loopIndex] cmp rax,[loopCount] jb short addHotkey_loop addHotkey_originalcode: //Restore registers mov rax,[rsp_plus_20_bak] mov [rsp+20],rax mov rax,[rax_bak] mov rbx,[rbx_bak] mov rcx,[rcx_bak] mov rdx,[rdx_bak] mov r8,[r8_bak] mov r9,[r9_bak] mov r10,[r10_bak] mov r11,[r11_bak] //call cheatengine-x86_64.exe+1BF540 //Original Code %REPLACE4% jmp addHotkey_return addHotkey_searchedAOB+3: jmp addHotkey_newmem addHotkey_return: ]==] --Grab and fill in offsets and calls, for CE version compatibility local TAddressList = getAddressList() MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE1%%",string.format(" dq %X",userDataToInteger(TAddressList))) local searchedAddr,machineCode,callAddr --Calls searchedAddr = getAddress("deleteHotkey_searchedAOB",true) machineCode = readIntegerLocal(searchedAddr+5) callAddr = searchedAddr+convertUIntToInt(machineCode)+9 MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE2%%",string.format("call %X",callAddr)) searchedAddr = getAddress("editHotkey_searchedAOB2",true) machineCode = readIntegerLocal(searchedAddr+9) callAddr = searchedAddr+convertUIntToInt(machineCode)+13 MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE3%%",string.format("call %X",callAddr)) searchedAddr = getAddress("addHotkey_searchedAOB",true) machineCode = readIntegerLocal(searchedAddr+4) callAddr = searchedAddr+convertUIntToInt(machineCode)+8 MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE4%%",string.format("call %X",callAddr)) --Offsets searchedAddr = getAddress("editHotkey_searchedAOB1",true) machineCode = readIntegerLocal(searchedAddr+3) MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE5%%",string.format("mov rax,[rbx+%X]",machineCode)) searchedAddr = getAddress("addHotkey_searchedAOB",true) machineCode = readIntegerLocal(searchedAddr-4) MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE6%%",string.format("mov rax,[rbx+%X]",machineCode)) searchedAddr = getAddress("isSelected_searchedAOB",true) machineCode = readIntegerLocal(searchedAddr+2) MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE7%%",string.format("cmp byte ptr [rbx+%X],#1",machineCode)) searchedAddr = getAddress("HotkeyListOffset_searchedAOB",true) machineCode = readIntegerLocal(searchedAddr+0x1E) MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE8%%",string.format("mov rax,[rax+%X]",machineCode)) MAIN_INJECT.Text = MAIN_INJECT.Text:gsub("%%REPLACE9%%",string.format("mov rbx,[rbx+%X]",machineCode)) autoAssemble(MAIN_INJECT.Text,true) --Remove registered symbols autoAssemble([[ //**********Cleanup*******************************************************************************// unregistersymbol(deleteHotkey_searchedAOB) unregistersymbol(editHotkey_searchedAOB1) unregistersymbol(editHotkey_searchedAOB2) unregistersymbol(addHotkey_searchedAOB) unregistersymbol(isSelected_searchedAOB) unregistersymbol(HotkeyListOffset_searchedAOB) ]],true) end