• Рубрика "Lua код сегодня" №6 (проверка по md5)

    Перенесена Статьи и видео md5 ce lua speak важно обучалка фишки
    1
    0 Голоса
    1 Сообщения
    246 Просмотры
    MasterGHM
    Получить md5 открытого процесса и записать его в MD5_CHEKING вручную \-- Функция для ручного вывода md5 ранее подключенного процесcа. Для установки MD5_CHEKING PrintMd5CurrentProcess() Пример проверки md5 function onOpenProcess(processid) reinitializeSymbolhandler() local md5Process = GetMd5Process(processid) PrintMd5Process(process, md5Process) local isSupportedVersion = CheckingMd5CurrentProcess(md5Process) local lineResult = isSupportedVersion and 'Is supported version.' or 'Is not supported version.' if not isSupportedVersion then speakEnglish(lineResult, false) messageDialog('Error', lineResult, mtError, mbClose) end end ce_md5.lua md5 - это алгоритм некоторой суммы байтов exe-шника. Позволит точно идентифицировать exe-шник, для которого будет сделана .CT таблица с указателями или сигнатурами. В случае несоответствия будет показан диалог сообщения и звуковое оповещение проговаривания текста ошибки. Будет необходимо проверять md5, чтобы смещения у структур точно не поменялись.
  • Поиск в региона памяти модуля

    Перенесена Статьи и видео фишки ce plugin обучалка
    5
    1
    0 Голоса
    5 Сообщения
    209 Просмотры
    PitronicP
    вот доказательство что старым версиям твой плагин нужен будет.
  • Большой брейкпоинт page exceptions

    Перенесена Статьи и видео breakpoint фишки ce lua
    1
    4
    0 Голоса
    1 Сообщения
    104 Просмотры
    MasterGHM
    Наткнувшись на тему вспомнил, что не все написал. В прошлом посте блога рассматривал бряк через DBVM. К сожалению, та версия dbvm из поста блога пропускала очень много инструкций и практически смысла нет её юзать. Например она определяла 16 инструкций, когда их было несколько тысяч, т.е. например 500 оффестов и на каждой по 10 инструкций. По DBVM надо, конечно, писать Дарк Байту, но желания нет. Так вот. Не только с DBVM можно ставить бряки на участок памяти. Есть еще тип брейкпоинтов page exceptions. О нем давно-давно известно и он как на ладони, но почему-то я пропустил его, когда искал оффсеты в структурах С ним можно работать с lua и без. Ловит огромное количество инструкций. Желательно мощное железо, т.к. игра скорее всего будет очень тормозить по 2-5 fps. Но на короткий запуск сойдет. 5 секунд и достаточно для снятия логов. На пару действий в игре тоже сойдет: выстрел или пермещение персонажа, прыжок или вообще ничего не делаем просто снимаем логи. способ поставить бряк из окна памяти. Подопытная программа "Tutorial-x86_64.exe" Здесь видно, что размер 720 байт Логи из окна инструкций CE 1000259AE - 48 8B 00 - mov rax,[rax] 1000259C3 - 48 8B 00 - mov rax,[rax] 10001D70C - F7 40 50 10000000 - test [rax+50],00000010 10001D734 - 48 8B 00 - mov rax,[rax] 1000AAB40 - 48 83 78 70 00 - cmp qword ptr [rax+70],00 10001D809 - F7 40 50 10000000 - test [rax+50],00000010 10000D452 - 48 8B 0A - mov rcx,[rdx] 10005AE70 - 83 40 68 01 - add dword ptr [rax+68],01 1000A4CF5 - F7 40 50 10000000 - test [rax+50],00000010 1000A4EB8 - 48 8B 00 - mov rax,[rax] 10000DA76 - 4C 8B 32 - mov r14,[rdx] 10005AE90 - 83 68 68 01 - sub dword ptr [rax+68],01 100139C13 - F7 40 50 10000000 - test [rax+50],00000010 100139C32 - 48 8B 48 60 - mov rcx,[rax+60] 100139C46 - 48 8B 40 60 - mov rax,[rax+60] 10009CEFB - 48 8B 00 - mov rax,[rax] 100098850 - 8B 80 80010000 - mov eax,[rax+00000180] 1000A4E81 - 81 88 00010000 00200000 - or [rax+00000100],00002000 1000A4E98 - 48 8B 00 - mov rax,[rax] 1000AD685 - F7 40 50 08000000 - test [rax+50],00000008 10009BFB8 - 8B 40 50 - mov eax,[rax+50] 10009816F - F7 40 50 08000000 - test [rax+50],00000008 100098236 - 48 8B 00 - mov rax,[rax] 10001BECE - 48 8B 00 - mov rax,[rax] 100098419 - F7 40 50 08000000 - test [rax+50],00000008 1000A2A28 - 48 8B 00 - mov rax,[rax] 1000A29F4 - 48 8B 12 - mov rdx,[rdx] 1000A4CC8 - 81 A0 00010000 FFDFFFFF - and [rax+00000100],FFFFDFFF 10001CC58 - F7 40 50 10000000 - test [rax+50],00000010 10000DB13 - 48 8B 00 - mov rax,[rax] 100095C65 - 48 8B 48 60 - mov rcx,[rax+60] 100095C75 - 48 8B 40 60 - mov rax,[rax+60] 10001CB04 - F7 40 50 10000000 - test [rax+50],00000010 10009BF35 - 8B 40 50 - mov eax,[rax+50] 10009932D - 48 8B 00 - mov rax,[rax] 10001F5C8 - F7 40 50 08000000 - test [rax+50],00000008 10001F638 - 8B 40 50 - mov eax,[rax+50] 100021803 - F7 40 50 08000000 - test [rax+50],00000008 100021923 - F7 40 50 08000000 - test [rax+50],00000008 10001ACB1 - 8B 41 50 - mov eax,[rcx+50] 10001B850 - 48 8B 48 60 - mov rcx,[rax+60] 10001B85C - 48 8B 40 60 - mov rax,[rax+60] 1000A2AC0 - 48 8B 00 - mov rax,[rax] 10013A2A3 - F7 40 50 10000000 - test [rax+50],00000010 10013A336 - 48 8B 00 - mov rax,[rax] 100098AC4 - 4C 8B 02 - mov r8,[rdx] 100098AD9 - 48 8B 00 - mov rax,[rax] 10013A35C - 48 8B 00 - mov rax,[rax] 10008A0C1 - 48 8B 00 - mov rax,[rax] 1000192A9 - 48 8B 12 - mov rdx,[rdx] 1000A3B99 - 48 8B 12 - mov rdx,[rdx] 100096636 - 8B 82 D0010000 - mov eax,[rdx+000001D0] 10008A0ED - 48 8B 00 - mov rax,[rax] 100097DF9 - 48 8B 00 - mov rax,[rax] 1000A4325 - 81 B8 80010000 FF7F0000 - cmp [rax+00000180],00007FFF 1000A6218 - F7 40 50 10000000 - test [rax+50],00000010 1000A6240 - 48 8B 00 - mov rax,[rax] 1000A6254 - 48 8B 00 - mov rax,[rax] 100097727 - 48 8B 48 60 - mov rcx,[rax+60] 100097733 - 48 8B 40 60 - mov rax,[rax+60] 10018E4D9 - F7 40 50 10000000 - test [rax+50],00000010 1000AA369 - F7 80 58010000 00400000 - test [rax+00000158],00004000 1000AA394 - 48 8B 00 - mov rax,[rax] 1000AA600 - 48 83 B8 B0020000 00 - cmp qword ptr [rax+000002B0],00 100097E3B - 48 8B 00 - mov rax,[rax] 1000A74A9 - 48 8B 00 - mov rax,[rax] Способ через Lua (подробнее в документации) debug_setBreakpoint(structure_address, sizeMemory, bptAccess, bpmException, onBreakpoint) P.S. Я написал про два способа установки брейкпоинта на множество адресов без DBVM. Вручную можно ставить такие брейкпоинты, но дальше уже кропотливый просмотр на предмет того чем это может помочь. Это может помочь определить типы данных и помочь прикинуть размер структуры, а также найти активные оффсеты. Можно на Lua автоматически определять активные offsets по базовому адресу структуры и эту структуру создать и заполнить в dessectData. Если будет время напишу скрипт.
  • Обработка исключения в Cheat Engine AA

    Перенесена Статьи и видео фишки ce aa exception
    1
    0 Голоса
    1 Сообщения
    70 Просмотры
    MasterGHM
    Новые директивы try/except в AA доступны Cheat Engine 6.8 Beta2 и выше Задача try/except в AA обработать исключение, не допустить crash. Чтобы игра продолжалась, а чит в лучшем случае не закрыл бы процесс. В теории возможно определить, что был crash и что-то сделать. Например, отправить логи в свой или иной удаленный сервис аналитики, что такой-то чит не сработал... Пример от DarkByte для try/exceptс счетчиком crashes [ENABLE] alloc(newmem,2048) alloc(crashcount,4) registersymbol(crashcount) label(returnhere) label(originalcode) label(exit) newmem: push eax {$try} mov eax,[esi+95c] cmp [eax+10],0 jmp ok {$except} pop eax add [crashcount],1 jmp originalcode ok: pop eax je aftersub //it is 0 originalcode: subss xmm0,xmm3 aftersub: movss [esi+00000164],xmm0 exit: jmp returnhere "HomeworldRM.exe"+22AEEA: jmp newmem nop nop nop nop nop nop nop returnhere: [DISABLE] dealloc(newmem) "HomeworldRM.exe"+22AEEA: subss xmm0,xmm3 movss [esi+00000164],xmm0 //Alt: db F3 0F 5C C3 F3 0F 11 86 64 01 00 00
  • Считаем размер инъекции в байтах

    Перенесена Статьи и видео ce lua фишки ce aa
    1
    2
    0 Голоса
    1 Сообщения
    69 Просмотры
    MasterGHM
    Можно подхватить разные моменты активации и деактивации записи в таблице CE и рассчитать размер кода между метками По шаблону вставляем АА код для туториала Cheat Engine Регистрируем метки-маркеры в АА коде Этими метками в Lua считаем и выводим ""endCode - startCode" размер байтов Пример, который подсчитал 15 байтов Пример скрипта {$lua} memrec.OnActivate = function (memoryrecord, before, currentstate) if currentstate and not before then print("Bytes: " .. getAddress("endCode - startCode")) end return before end {$ASM} [ENABLE] //code from here to '[DISABLE]' will be used to enable the cheat aobscanmodule(INJECT,Tutorial-i386.exe,81 BB 80 04 00 00 E8 03 00 00) // should be unique alloc(newmem,$1000) label(code) label(endCode) label(startCode) registerSymbol(startCode) registerSymbol(endCode) newmem: code: startCode: cmp [ebx+00000480],000003E8 jmp return endCode: INJECT: jmp newmem nop nop nop nop nop return: registersymbol(INJECT) [DISABLE] //code from here till the end of the code will be used to disable the cheat INJECT: db 81 BB 80 04 00 00 E8 03 00 00 unregistersymbol(startCode) unregistersymbol(endCode) unregistersymbol(INJECT) dealloc(newmem) { // ORIGINAL CODE - INJECTION POINT: "Tutorial-i386.exe"+23FE3 "Tutorial-i386.exe"+23FD1: C9 - leave "Tutorial-i386.exe"+23FD2: C3 - ret "Tutorial-i386.exe"+23FD3: 00 00 - add [eax],al "Tutorial-i386.exe"+23FD5: 00 00 - add [eax],al "Tutorial-i386.exe"+23FD7: 00 00 - add [eax],al "Tutorial-i386.exe"+23FD9: 00 00 - add [eax],al "Tutorial-i386.exe"+23FDB: 00 00 - add [eax],al "Tutorial-i386.exe"+23FDD: 00 00 - add [eax],al "Tutorial-i386.exe"+23FDF: 00 53 89 - add [ebx-77],dl "Tutorial-i386.exe"+23FE2: C3 - ret // ---------- INJECTING HERE ---------- "Tutorial-i386.exe"+23FE3: 81 BB 80 04 00 00 E8 03 00 00 - cmp [ebx+00000480],000003E8 // ---------- DONE INJECTING ---------- "Tutorial-i386.exe"+23FED: 75 2C - jne Tutorial-i386.exe+2401B "Tutorial-i386.exe"+23FEF: 8B 83 68 04 00 00 - mov eax,[ebx+00000468] "Tutorial-i386.exe"+23FF5: B2 01 - mov dl,01 "Tutorial-i386.exe"+23FF7: 8B 8B 68 04 00 00 - mov ecx,[ebx+00000468] "Tutorial-i386.exe"+23FFD: 8B 09 - mov ecx,[ecx] "Tutorial-i386.exe"+23FFF: FF 91 20 02 00 00 - call dword ptr [ecx+00000220] Документация кому интересно MemoryRecord Class: The memoryrecord objects are the entries you see in the addresslist properties ID: Integer - Unique ID Index: Integer - The index ID for this record. 0 is top. (ReadOnly) Description: string- The description of the memory record Address: string - Get/set the interpretable address string. Useful for simple address settings. AddressString: string - Get the address string shown in CE (ReadOnly) OffsetCount: integer - The number of offsets. Set to 0 for a normal address Offset[] : integer - Array to access each offset OffsetText[] : string - Array to access each offset using the interpretable text style CurrentAddress: integer - The address the memoryrecord points to VarType: ValueType (string) - The variable type of this record. See vtByte to vtCustom Type: ValueType (number) - The variable type of this record. See vtByte to vtCustom If the type is vtString then the following properties are available: String.Size: Number of characters in the string String.Unicode: boolean String.Codepage: boolean If the type is vtBinary then the following properties are available Binary.Startbit: First bit to start reading from Binary.Size : Number of bits If the type is vtByteArray then the following properties are available Aob.Size : Number of bytes CustomTypeName: String - If the type is vtCustom this will contain the name of the CustomType Script: String - If the type is vtAutoAssembler this will contain the auto assembler script Value: string - The value in stringform. Selected: boolean - Set to true if selected (ReadOnly) Active: boolean - Set to true to activate/freeze, false to deactivate/unfreeze Color: integer ShowAsHex: boolean - Self explanatory ShowAsSigned: boolean - Self explanatory AllowIncrease: boolean - Allow value increasing, unfreeze will reset it to false AllowDecrease: boolean - Allow value decreasing, unfreeze will reset it to false Collapsed: boolean - Set to true to collapse this record or false to expand it. Use expand/collapse methods for recursive operations. IsGroupHeader: boolean - Set to true if the record was created as a Group Header with no address or value info. (ReadOnly) IsReadable: boolean - Set to false if record contains an unreadable address. NOTE: This property will not be set until the value property is accessed at least once. (ReadOnly) Options: String set - a string enclosed by square brackets filled with the options seperated by a comma. Valid options are: moHideChildren, moActivateChildrenAsWell, moDeactivateChildrenAsWell, moRecursiveSetValue, moAllowManualCollapseAndExpand, moManualExpandCollapse DropDownLinked: boolean - if dropdown list refers to list of another memory record eg. (memrec name) DropDownLinkedMemrec: string - Description of linked memrec or emptystring if not linked DropDownList : StringList - list of "value:description" lines, lists are still separate objects when linked, read-write DropDownReadOnly: boolean - true if 'Disallow manual user input' is set DropDownDescriptionOnly: boolean - self explanatory DisplayAsDropDownListItem: boolean - self explanatory DropDownCount: integer - equivalent to .DropDownList.Count DropDownValue[index] : Array to access values in DropDownList (ReadOnly) DropDownDescription[index] : Array to access Descriptions in DropDownList (ReadOnly) Count: Number of children Child[index] : Array to access the child records [index] = Child[index] Parent: MemoryRecord - self explanatory HotkeyCount: integer - Number of hotkeys attached to this memory record Hotkey[] : Array to index the hotkeys Async: Boolean - Set to true if activating this entry will be asynchronious. (only for AA/Lua scripts) AsyncProcessing: Boolean - True when async is true and it's being processed AsyncProcessingTime: qword - The time that it has been processing in milliseconds OnActivate: function(memoryrecord,before,currentstate):boolean - The function to call when the memoryrecord will change (or changed) Active to true. If before is true, not returning true will cause the activation to stop. OnDeactivate: function(memoryrecord,before,currentstate):boolean - The function to call when the memoryrecord will change (or changed) Active to false. If before is true, not returning true will cause the deactivation to stop. OnDestroy: function() - Called when the memoryrecord is destroyed. OnGetDisplayValue: function(memoryrecord,valuestring):boolean,string - This function gets called when rendering the value of a memory record. Return true and a new string to override the value shown DontSave: boolean - Don't save this memoryrecord and it's children methods getDescription() setDescription() getAddress() : Returns the interpretable addressstring of this record. If it is a pointer, it returns a second result as a table filled with the offsets setAddress(string) : Sets the interpretable address string, and if offsets are provided make it a pointer getOffsetCount(): Returns the number of offsets for this memoryrecord setOffsetCount(integer): Lets you set the number of offsets getOffset(index) : Gets the offset at the given index setOffset(index, value) : Sets the offset at the given index getCurrentAddress(): Returns the current address as an integer (the final result of the interpretable address and pointer offsets) appendToEntry(memrec): Appends the current memory record to the given memory record getHotkey(index): Returns the hotkey from the hotkey array getHotkeyByID(integer): Returns the hotkey with the given id reinterpret() createHotkey({keys}, action, value OPTIONAL): Returns a hotkey object disableWithoutExecute(): Sets the entry to disabled without executing the disable section global events function onMemRecPreExecute(memoryrecord, newstate BOOLEAN): If above function is defined it will be called before action* has been performed. Active property is about to change to newState. function onMemRecPostExecute(memoryrecord, newState BOOLEAN, succeeded BOOLEAN): If above function is defined it will be called after action*. Active property was supposed to change to newState. If 'succeeded' is true it means that Active state has changed and is newState. newState and succeeded are read only. *action can be: running auto assembler script (ENABLE or DISABLE section), freezing and unfreezing.
  • Выполить текст, как код

    Перенесена Статьи и видео фишки ce lua loadstring
    1
    0 Голоса
    1 Сообщения
    68 Просмотры
    MasterGHM
    Функция loadstring исполняет строку кода как функцию. f = loadstring ("print 'hello, world'") f () --> hello, world Есть еще и такая функция как string.dump. Она создает строку из функции function f () print "hello, world" end s = string.dump (f) \-- Можно строку тут же запустить как код loadstring (s) () --> hello, world Если по обратной связи строить и исполнять строку кода, то предположительно можно генерировать код другим кодом и учитывать гораздо больше условий, чем это может сделать человек. Пригодится для ИИ отладки и для ИИ бота. Код пишет другой код по обратной связи. Реальность?
  • Асинхронное выполнение сценариев

    Перенесена Статьи и видео ce .ct ce aa ce async фишки
    1
    5
    0 Голоса
    1 Сообщения
    83 Просмотры
    MasterGHM
    Записи в таблице CE представим как сценарии, которые должны выполнятся асинхронно. Т.е. они что-от делают некоторое время одновременно, например, сканируют память. При этом ничего зависает. Для этого будем актировать такую опцию Если эту опцию поставить на записи, то появляются вот такие часики АА-шные скрипты могут искать в этот момент сигнатуру. Lua скрипты потестить было интересно, узнать действительно ли асинхронно выполняется. Например, один скрипт выполняет счет, второй выполняет счет. По выполнении выводится результат. [ENABLE] {$lua} local _, counter, _, async = memrec.Description:match('(Cunt.=.)(%d*).*(Async.=.)(%w*)') memrec.Async = async == 'true' for i = 1, counter do end local currentTime = os.date("%c"):gsub('/','.') print('Finish record:' .. memrec.Description..', at time ' .. currentTime) memrec.Active = false function onMemRecPostExecute(memoryrecord, newState, succeeded) if (memoryrecord == memrec and newState == true) then memrec.Active = false end end {$asm} [DISABLE] После выполнения Если продублировать 4 скрипта, то видим, что нельзя запустить асинхронно более двух скриптов Вот такой вариант еще [ENABLE] {$Lua} function threadFunction(th) th.freeOnTerminate(false) th.Name = 'myThread' for b = 1, 200000000 do --checkSynchronize() end --while not th.Terminated do -- myvar=myvar+1 -- synchronize(function() MainForm.Caption = 'myvar '..myvar end) -- sleep(2000) --end synchronize(function() print("1") end) end --myvar=0 local myThread = createNativeThreadSuspended(threadFunction) myThread.resume() {$Asm} [DISABLE] {$Lua} if myThread then myThread.terminate() myThread.waitfor() myThread.destroy() myThread=nil end {$Asm} таблица Asynchronous testing.CT
  • Делаем EFLAGS таблицу

    Перенесена Статьи и видео шаблоны фишки ce lua
    3
    2
    0 Голоса
    3 Сообщения
    130 Просмотры
    MasterGHM
    Ответил
  • Выход из рутины до ближайшего цикла

    Перенесена Статьи и видео шаблоны ce lua фишки
    1
    1
    0 Голоса
    1 Сообщения
    77 Просмотры
    MasterGHM
    собенности переход на следующий адрес по инструкциям ветвления вычисляется Lua кодом по ret, jmp, jmp condition до исполнения кода определение опкодов ветвления по readmem без дизассемблериования по тестам последний брейкпоинт снимается на ближайшем цикле Пример лога до близжайшего цикла, когда поднимается из рутины вверх > RET :00454684 - C3 - ret > -->> :0045468C - 5B - pop ebx > RET :0045468F - C3 - ret > -->> :00454695 - C3 - ret > RET :00454695 - C3 - ret > -->> :00437F36 - 5B - pop ebx > RET :00437F37 - C3 - ret > -->> :004272EB - 5B - pop ebx > RET :004272EC - C3 - ret > -->> :004273E9 - 5E - pop esi > RET :004273EA - C3 - ret > -->> :00437A2E - 5F - pop edi > RET :00437A34 - C3 - ret > -->> :0043B749 - 5B - pop ebx > RET :0043B74D - C3 - ret > -->> :00427195 - 5F - pop edi > RET :00427198 - C3 - ret > -->> :004376BB - 8B 45 FC - mov eax,[ebp-04] > RET :004376C2 - C2 0400 - ret 0004 > -->> :0043B880 - 89 46 0C - mov [esi+0C],eax > RET :0043B88A - C3 - ret > -->> :0043BFF4 - 84 C0 - test al,al > isCJMP :0043BFF6 - 75 09 - jne 0043C001 > RET :0043C003 - C3 - ret > -->> :0044DFAD - 5E - pop esi > RET :0044DFAF - C3 - ret > -->> :00437A2E - 5F - pop edi \--[[ Версия: 0.01.b1 Выход из рутины до близжайшего цикла ]]-- mainAddress = 0x0045B5A4 -- адрес некоторого параметра в игре nextAddress = nil is64bits = targetIs64Bit() tableInstruction ={} tableBreakpointsAddress ={} function ContaintsBeakPoint(address) for i = 1, #tableBreakpointsAddress do if tableBreakpointsAddress[i] == address then return true end end return false end \-- Возвращает адрес по ret function GetNextAddressFromRET(address) if is64bits then nextAddress = readPointer(RSP) else nextAddress = readPointer(ESP) end return nextAddress end \-- Возвращает адрес по Jmp function GetNextAddressFromJMP(address) local disassembledstring = nil if is64bits then local disassembledstring = disassemble(RIP) else local disassembledstring = disassemble(EIP) end local _, opcode, _, _ = splitDisassembledString(disassembledstring) return GetAddressFromOpcode(opcode) end function ToBits(num, bits) local t = {} for b = bits, 1, -1 do rest = math.fmod(num,2) t[b] = math.floor(rest) num = (num-rest)/2 end if num == 0 then return t else return {'Not enough bits to represent this number'} end end function GetEFLAGS() local bitsTable = ToBits(EFLAGS, 16) local tableEFLAGS = { OF = bitsTable[17-12], DF = bitsTable[17-11], SF = bitsTable[17-8], ZF = bitsTable[17-7], AF = bitsTable[17-5], PF = bitsTable[17-3], CF = bitsTable[17-1] } --for k,v in pairs(tableEFLAGS) do -- print (k..' = '..v) --end -- --print(EFLAGS) --local s = '' --for i=1,#bitsTable do -- s = s..bitsTable[i] --end --print(s) return tableEFLAGS end \-- Возвращает адрес из опкода jmp dword ptr [edi*4+07895D88] или jmp 07895D88 \--print(string.format('%08X', newAddress)) function GetAddressFromOpcode (opcode) local rightLine = string.match(opcode, '%S*%s*(%S*)') local isPointer = string.match(opcode, '%[') if isPointer then rightLine = string.match(opcode, '%[(.*)%]') --00454664 - 8B 83 60030000 - mov eax,[ebx+00000360] if string.match(opcode, 'eax') then rightLine = string.gsub(rightLine, 'eax', EAX) end if string.match(opcode, 'ebx') then rightLine = string.gsub(rightLine, 'ebx', EBX) end if string.match(opcode, 'ecx') then rightLine = string.gsub(rightLine, 'ecx', ECX) end if string.match(opcode, 'edx') then rightLine = string.gsub(rightLine, 'edx', EDX) end if string.match(opcode, 'esi') then rightLine = string.gsub(rightLine, 'esi', ESI) end if string.match(opcode, 'edi') then rightLine = string.gsub(rightLine, 'edi', EDI) end if string.match(opcode, 'esp') then rightLine = string.gsub(rightLine, 'esp', ESP) end if string.match(opcode, 'ebp') then rightLine = string.gsub(rightLine, 'ebp', EBP) end if is64bits then if string.match(opcode, 'rax') then rightLine = string.gsub(rightLine, 'rax', RAX) end if string.match(opcode, 'rbx') then rightLine = string.gsub(rightLine, 'rbx', RBX) end if string.match(opcode, 'rcx') then rightLine = string.gsub(rightLine, 'rcx', RCX) end if string.match(opcode, 'rdx') then rightLine = string.gsub(rightLine, 'rdx', RDX) end if string.match(opcode, 'rsi') then rightLine = string.gsub(rightLine, 'rsi', RSI) end if string.match(opcode, 'rdi') then rightLine = string.gsub(rightLine, 'rdi', RDI) end if string.match(opcode, 'rsp') then rightLine = string.gsub(rightLine, 'rsp', RSP) end if string.match(opcode, 'rbp') then rightLine = string.gsub(rightLine, 'rbp', RBP) end if string.match(opcode, 'r8') then rightLine = string.gsub(rightLine, 'r8', R8) end if string.match(opcode, 'r9') then rightLine = string.gsub(rightLine, 'r9', R9) end if string.match(opcode, 'r10') then rightLine = string.gsub(rightLine, 'r10', R10) end if string.match(opcode, 'r11') then rightLine = string.gsub(rightLine, 'r11', R11) end if string.match(opcode, 'r12') then rightLine = string.gsub(rightLine, 'r12', R12) end if string.match(opcode, 'r13') then rightLine = string.gsub(rightLine, 'r13', R13) end if string.match(opcode, 'r14') then rightLine = string.gsub(rightLine, 'r14', R14) end if string.match(opcode, 'r15') then rightLine = string.gsub(rightLine, 'r15', R15) end end return getAddress('%['..rightLine..'%]') end return getAddress(rightLine) end \-- Возвращает адрес по Jmp condition, когда тот выполняется или не выполняется function GetNextAddressFromConditionJMP(address, size) local _,opcode,_,_ = splitDisassembledString(disassemble(address)) local leftString = string.match(opcode, '%S*') local eflags = GetEFLAGS() if (leftString == 'jnz' or leftString == 'jne') then if eflags.ZF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'je' or leftString == 'jz') then if eflags.ZF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jg' or leftString == 'jnle') then if eflags.ZF == 0 and eflags.SF == eflags.OF then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jb' or leftString == 'jc' or leftString == 'jnae') then if eflags.CF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jae') then if eflags.CF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'ja') then if eflags.CF == 0 and eflags.ZF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jbe') then if eflags.CF == 1 and eflags.ZF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jl' or leftString == 'jnge') then if eflags.SF ~= eflags.OF then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jle' or leftString == 'jng') then if eflags.ZF == 1 or eflags.SF ~= eflags.OF then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jna') then if eflags.CF == 1 or eflags.ZF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jc') then if eflags.CF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jp' or leftString == 'jpe') then if eflags.PF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jnp' or leftString == 'jpo') then if eflags.PF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jnb' or leftString == 'jnc') then if eflags.CF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jnbe') then if eflags.CF == 0 and eflags.ZF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jno') then if eflags.OF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jns') then if eflags.SF == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jo') then if eflags.OF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'js') then if eflags.SF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jge' or leftString == 'jnl') then if eflags.CF == 1 and eflags.OF == 1 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jrcxz') then if RCX == 0 then return GetAddressFromOpcode(opcode) end elseif (leftString == 'jecxz') then if ECX == 0 then return GetAddressFromOpcode(opcode) end end return address + size end function IsRet(address) local value = readBytes(address,1, false) return value == 0xC3 or value == 0xCB or value == 0xC2 or value == 0xCA end function IsCall(address) local value = readBytes(address,1, false) return value == 0xFF or value == 0xE8 -- or value == 0x9A end function IsJMP(address) local value = readBytes (address, 1, false) if value == 0xFF then if readBytes (address + 1, 1, false) == 05 then return false end end return value == 0xEB or value == 0xE9 or value == 0xFF -- or value == 0xEA \--[[ 078921A8 - EB 38 - jmp 078921E2 0789242D - E9 E2000000 - jmp 07892514 07894F4C - FF E2 - jmp edx 07895C67 - FF 24 BD 885D8907 - jmp dword ptr [edi*4+07895D88] ]]-- end function IsConditionJMP(address) local value = readBytes (address, 1, false) return value == 0x77 or value == 0x73 or value == 0x72 or value == 0x76 or value == 0xE3 or value == 0x74 or value == 0x7F or value == 0x7D or value == 0x7C or value == 0x7E or value == 0x75 or value == 0x71 or value == 0x7B or value == 0x79 or value == 0x70 or value == 0x7A or value == 0x78 or value == 0x0F end \-- Возвращает адрес, на который, будет прыжок function GetNextAddress(addressXIP) -- Определить на какой инструкции мы находимся, чтобы узнать на какую следующу инструкцию ставить бряк -- ret - прыжок по смещению ESP/RSP -- jmp - прыжок без условия -- je, jne, jxx - прыжок с улосвием -- Определить размер инструкции, тип инструкции на текущем addressXIP local findIndex = -1 for i = 1, #tableInstruction do if tableInstruction[i].XIP == addressXIP then findIndex = i break end end local size = 0 local isRet = false local isJMP = false local isCJMP = false if findIndex == -1 then -- Если нет данных ---------------- ЗАПОМИНАТЬ РАЗМЕР ИНСТРУКЦИИ (чтобы не дизассемблировать повторно) size = getInstructionSize(addressXIP) isRet = IsRet(addressXIP) isJMP = IsJMP(addressXIP) isCJMP = IsConditionJMP(addressXIP) table.insert(tableInstruction, {XIP = addressXIP, SIZE = size, ISRET = isRet, ISJMP = isJMP, ISCJMP = isCJMP}) else -- Если данные есть size = tableInstruction[findIndex].SIZE isRet = tableInstruction[findIndex].ISRET isJMP = tableInstruction[findIndex].ISJMP isCJMP = tableInstruction[findIndex].ISCJMP end --------------- if isRet then print('> RET :' ..disassemble(nextAddress)) nextAddress = GetNextAddressFromRET(addressXIP) print('> -->> :' ..disassemble(nextAddress)) elseif isJMP then print('> isJMP :' ..disassemble(nextAddress)) nextAddress = GetNextAddressFromJMP(addressXIP) elseif isCJMP then print('> isCJMP :' ..disassemble(nextAddress)) nextAddress = GetNextAddressFromConditionJMP(addressXIP, size) else nextAddress = addressXIP + size end return nextAddress end function debugger_onBreakpoint() local isContaintsBreakPoint = false -- Удалить прошлый брейкпоинт if(nextAddress ~= nil) then isContaintsBreakPoint = ContaintsBeakPoint(nextAddress) if isContaintsBreakPoint then debug_removeBreakpoint(nextAddress) end end -- Поставить брейкпоинт на следующую инструкцию не входя в call-ы local XIP = 0 if is64bits then XIP = EIP else XIP = RIP end nextAddress = GetNextAddress(XIP) if not ContaintsBeakPoint(nextAddress) then debug_setBreakpoint(nextAddress, 1, bptExecute, bpmDebugRegister) table.insert(tableBreakpointsAddress, nextAddress) end return 1 --1 не показывать дизассемблер end if getOpenedProcessID() == 0 then openProcess('test.exe') end \--bptWrite \--bptAccess debug_removeBreakpoint() debug_setBreakpoint(mainAddress, 4, bptWrite, bpmDebugRegister) Справка 77 cb JA rel8 D Valid Valid Jump short if above (CF=0 and ZF=0). 73 cb JAE rel8 D Valid Valid Jump short if above or equal (CF=0). 72 cb JB rel8 D Valid Valid Jump short if below (CF=1). 76 cb JBE rel8 D Valid Valid Jump short if below or equal (CF=1 or ZF=1). 72 cb JC rel8 D Valid Valid Jump short if carry (CF=1). E3 cb JCXZ rel8 D N.E. Valid Jump short if CX register is 0. E3 cb JECXZ rel8 D Valid Valid Jump short if ECX register is 0. E3 cb JRCXZ rel8 D Valid N.E. Jump short if RCX register is 0. 74 cb JE rel8 D Valid Valid Jump short if equal (ZF=1). 7F cb JG rel8 D Valid Valid Jump short if greater (ZF=0 and SF=OF). 7D cb JGE rel8 D Valid Valid Jump short if greater or equal (SF=OF). 7C cb JL rel8 D Valid Valid Jump short if less (SF≠ OF). 7E cb JLE rel8 D Valid Valid Jump short if less or equal (ZF=1 or SF≠ OF). 76 cb JNA rel8 D Valid Valid Jump short if not above (CF=1 or ZF=1). 72 cb JNAE rel8 D Valid Valid Jump short if not above or equal (CF=1). 73 cb JNB rel8 D Valid Valid Jump short if not below (CF=0). 77 cb JNBE rel8 D Valid Valid Jump short if not below or equal (CF=0 andZF=0). 73 cb JNC rel8 D Valid Valid Jump short if not carry (CF=0). 75 cb JNE rel8 D Valid Valid Jump short if not equal (ZF=0). 7E cb JNG rel8 D Valid Valid Jump short if not greater (ZF=1 or SF≠ OF). 7C cb JNGE rel8 D Valid Valid Jump short if not greater or equal (SF≠ OF). 7D cb JNL rel8 D Valid Valid Jump short if not less (SF=OF). 7F cb JNLE rel8 D Valid Valid Jump short if not less or equal (ZF=0 and SF=OF). 71 cb JNO rel8 D Valid Valid Jump short if not overflow (OF=0). 7B cb JNP rel8 D Valid Valid Jump short if not parity (PF=0). 79 cb JNS rel8 D Valid Valid Jump short if not sign (SF=0). 75 cb JNZ rel8 D Valid Valid Jump short if not zero (ZF=0). 70 cb JO rel8 D Valid Valid Jump short if overflow (OF=1). 7A cb JP rel8 D Valid Valid Jump short if parity (PF=1). 7A cb JPE rel8 D Valid Valid Jump short if parity even (PF=1). 7B cb JPO rel8 D Valid Valid Jump short if parity odd (PF=0). 78 cb JS rel8 D Valid Valid Jump short if sign (SF=1). 74 cb JZ rel8 D Valid Valid Jump short if zero (ZF = 1). 0F 87 cw JA rel16 D N.S. Valid Jump near if above (CF=0 and ZF=0). Not supported in 64-bit mode. 0F 87 cd JA rel32 D Valid Valid Jump near if above (CF=0 and ZF=0). 0F 83 cw JAE rel16 D N.S. Valid Jump near if above or equal (CF=0). Not supported in 64-bit mode. 0F 83 cd JAE rel32 D Valid Valid Jump near if above or equal (CF=0). 0F 82 cw JB rel16 D N.S. Valid Jump near if below (CF=1). Not supported in 64-bit mode. 0F 82 cd JB rel32 D Valid Valid Jump near if below (CF=1). 0F 86 cw JBE rel16 D N.S. Valid Jump near if below or equal (CF=1 or ZF=1). Not supported in 64-bit mode. 0F 86 cd JBE rel32 D Valid Valid Jump near if below or equal (CF=1 or ZF=1). 0F 82 cw JC rel16 D N.S. Valid Jump near if carry (CF=1). Not supported in 64-bit mode. 0F 82 cd JC rel32 D Valid Valid Jump near if carry (CF=1). 0F 84 cw JE rel16 D N.S. Valid Jump near if equal (ZF=1). Not supported in 64-bit mode. 0F 84 cd JE rel32 D Valid Valid Jump near if equal (ZF=1). 0F 84 cw JZ rel16 D N.S. Valid Jump near if 0 (ZF=1). Not supported in 64-bit mode. 0F 84 cd JZ rel32 D Valid Valid Jump near if 0 (ZF=1). 0F 8F cw JG rel16 D N.S. Valid Jump near if greater (ZF=0 and SF=OF). Notsupported in 64-bit mode. 0F 8F cd JG rel32 D Valid Valid Jump near if greater (ZF=0 and SF=OF). 0F 8D cw JGE rel16 D N.S. Valid Jump near if greater or equal (SF=OF). Not supported in 64-bit mode. 0F 8D cd JGE rel32 D Valid Valid Jump near if greater or equal (SF=OF). 0F 8C cw JL rel16 D N.S. Valid Jump near if less (SF≠ OF). Not supported in 64-bit mode. 0F 8C cd JL rel32 D Valid Valid Jump near if less (SF≠ OF). 0F 8E cw JLE rel16 D N.S. Valid Jump near if less or equal (ZF=1 or SF≠ OF). Not supported in 64-bit mode. 0F 8E cd JLE rel32 D Valid Valid Jump near if less or equal (ZF=1 or SF≠ OF). 0F 86 cw JNA rel16 D N.S. Valid Jump near if not above (CF=1 or ZF=1). Not supported in 64-bit mode. 0F 86 cd JNA rel32 D Valid Valid Jump near if not above (CF=1 or ZF=1). 0F 82 cw JNAE rel16 D N.S. Valid Jump near if not above or equal (CF=1). Not supported in 64-bit mode. 0F 82 cd JNAE rel32 D Valid Valid Jump near if not above or equal (CF=1). 0F 83 cw JNB rel16 D N.S. Valid Jump near if not below (CF=0). Not supported in 64-bit mode. 0F 83 cd JNB rel32 D Valid Valid Jump near if not below (CF=0). 0F 87 cw JNBE rel16 D N.S. Valid Jump near if not below or equal (CF=0 and ZF=0). Not supported in 64-bit mode. 0F 87 cd JNBE rel32 D Valid Valid Jump near if not below or equal (CF=0 and ZF=0). 0F 83 cw JNC rel16 D N.S. Valid Jump near if not carry (CF=0). Not supported in 64-bit mode. 0F 83 cd JNC rel32 D Valid Valid Jump near if not carry (CF=0). 0F 85 cw JNE rel16 D N.S. Valid Jump near if not equal (ZF=0). Not supported in 64-bit mode. 0F 85 cd JNE rel32 D Valid Valid Jump near if not equal (ZF=0). 0F 8E cw JNG rel16 D N.S. Valid Jump near if not greater (ZF=1 or SF≠ OF). Not supported in 64-bit mode. 0F 8E cd JNG rel32 D Valid Valid Jump near if not greater (ZF=1 or SF≠ OF). 0F 8C cw JNGE rel16 D N.S. Valid Jump near if not greater or equal (SF≠ OF). Not supported in 64-bit mode. 0F 8C cd JNGE rel32 D Valid Valid Jump near if not greater or equal (SF≠ OF). 0F 8D cw JNL rel16 D N.S. Valid Jump near if not less (SF=OF). Not supported in 64-bit mode. 0F 8D cd JNL rel32 D Valid Valid Jump near if not less (SF=OF). 0F 8F cw JNLE rel16 D N.S. Valid Jump near if not less or equal (ZF=0 and SF=OF). Not supported in 64-bit mode. 0F 8F cd JNLE rel32 D Valid Valid Jump near if not less or equal (ZF=0 and SF=OF). 0F 81 cw JNO rel16 D N.S. Valid Jump near if not overflow (OF=0). Not supported in 64-bit mode. 0F 81 cd JNO rel32 D Valid Valid Jump near if not overflow (OF=0). 0F 8B cw JNP rel16 D N.S. Valid Jump near if not parity (PF=0). Not supported in 64-bit mode. 0F 8B cd JNP rel32 D Valid Valid Jump near if not parity (PF=0). 0F 89 cw JNS rel16 D N.S. Valid Jump near if not sign (SF=0). Not supported in 64-bit mode. 0F 89 cd JNS rel32 D Valid Valid Jump near if not sign (SF=0). 0F 85 cw JNZ rel16 D N.S. Valid Jump near if not zero (ZF=0). Not supported in 64-bit mode. 0F 85 cd JNZ rel32 D Valid Valid Jump near if not zero (ZF=0). 0F 80 cw JO rel16 D N.S. Valid Jump near if overflow (OF=1). Not supported in 64-bit mode. 0F 80 cd JO rel32 D Valid Valid Jump near if overflow (OF=1). 0F 8A cw JP rel16 D N.S. Valid Jump near if parity (PF=1). Not supported in 64-bit mode. 0F 8A cd JP rel32 D Valid Valid Jump near if parity (PF=1). 0F 8A cw JPE rel16 D N.S. Valid Jump near if parity even (PF=1). Not supported in 64-bit mode. 0F 8A cd JPE rel32 D Valid Valid Jump near if parity even (PF=1). 0F 8B cw JPO rel16 D N.S. Valid Jump near if parity odd (PF=0). Not supported in 64-bit mode. 0F 8B cd JPO rel32 D Valid Valid Jump near if parity odd (PF=0). 0F 88 cw JS rel16 D N.S. Valid Jump near if sign (SF=1). Not supported in 64-bit mode. 0F 88 cd JS rel32 D Valid Valid Jump near if sign (SF=1). 0F 84 cw JZ rel16 D N.S. Valid Jump near if 0 (ZF=1). Not supported in 64-bit mode. 0F 84 cd JZ rel32 D Valid Valid Jump near if 0 (ZF=1). Если трейсить трейслогом 1000 инструкций поверх call, то видим многократное повторение пути внутри цикла между 00437A34 и 0044DFAF. С помощью скрипта можно выйти на цикл не используя трейслог Можно использоваться функции определения куда прыгнет поток, до его выполнения. Можно оперировать таблицей адресов с брейкпоинтами в пошаговой отладке.
  • Оптимизация splitDisassembledString()

    Перенесена Статьи и видео ce lua optimization фишки
    1
    0 Голоса
    1 Сообщения
    678 Просмотры
    MasterGHM
    Напишем функцию, которая в 3.2 раз быстрее splitDisassembledString(disassemble(address)) \-- Линия: 0045464A - FF 05 A4B54500 - inc [0045B5A4] { [000003EA] } function GetDebugString(address) return splitDisassembledString(disassemble(address)) end \-- address, bytes, opcode function GetDebugString2(address) local clearString = string.gsub(disassemble(address), '%s','') return string.match(clearString, '^(.-)%-(.-)%-(.-)$') end function NoOptimizeCode() GetDebugString(0x0045464A) end function OptimizeCode() GetDebugString2(0x0045464A) end local countRepeat = 100000 -- add more cycle local x1 = 0 local x2 = 0 x1 = getTickCount() for i = 1, countRepeat do NoOptimizeCode() end x2 = getTickCount() for i = 1, countRepeat do OptimizeCode() end print(string.format("%.2f", (x2 - x1)/(getTickCount() - x2)) ) Сравнивая скорости получаем оптимизацию в ~3.20 раза быстрее. Пример использования function GetDebugString2(address) local clearString = string.gsub(disassemble(address), '%s','') return string.match(clearString, '^(.-)%-(.-)%-(.-)$') end local address, bytes, opcode = GetDebugString2(0x0045464A) print(address) print(bytes) print(opcode) gsub очищает пробелы, а выражение '^(.-)%-(.-)%-(.-)$' позволит захватить данные между тире в строке. Может пригодится, когда трейсим своим Lua кодом. Если заинтересовали регулярки: ссылка
  • Пошаговая отладка Lua скриптов

    Перенесена Статьи и видео debug ce lua фишки
    2
    1
    0 Голоса
    2 Сообщения
    225 Просмотры
    MasterGHM
    Открываем Lua консоль из дизассемблера Пишем Lua скрипт Дальше по шагам как на картинке Если мы пишем какую-то функцию и она дает сбой, то её можно отладить как на скриншоте. Это может быть и не функция. Например, код прочитал какой-то файл с текстом сохраненных параметров и подсмотрели в пошаговой Lua отладке что происходит дальше. *Действуют горячие клавиши. Например, F7— шаг, F9 — запуск без остановки.
  • Заполненение таблицы данными по базовому адресу

    Перенесена Статьи и видео фишки ce lua ce memrec ce aa
    1
    2
    0 Голоса
    1 Сообщения
    102 Просмотры
    MasterGHM
    Нажали checkbox — заполнились данные по базовому адресу Отжали checkbox — удалились данные [ENABLE] {$lua} baseAddress = 0x40000000 function FillValues(baseAddress, userValue) stringData = [[ Голод 20 Болезнь -10 Депрессия -40 Усталость 8 Ранения -28 Скрытность 6c Изготовление 84 Исследования 54 Собирательство 3c Охота b4 Рыбалка e4 Сбор cc Готовка 9c Сила 114 Ловкость fc Телосложение 144 Борьба 12c Интелект 1a4 Речь 174 Медицина 18c Знания 15c ]] -- Захват данных включая знак for name, value in stringData:gmatch('(%S+).-(%S?%x+)') do local stringPointer = '' local indexMinus = value:find('-') if indexMinus then stringPointer = string.format('[%08X - %s]', baseAddress, value:sub(indexMinus + 1)) else stringPointer = string.format('[%08X + %s]', baseAddress, value) end -- Добавить дочерний memrec -- memrec это ссылка на memrec, в котором написан этот скрипт local newMemRect = getAddressList().createMemoryRecord() newMemRect.Description = name newMemRect.Address = stringPointer newMemRect.Type = vtDword newMemRect.appendToEntry(memrec) end end \-- Запись userValue по baseAddress FillValues(baseAddress, userValue) [DISABLE] {$lua} for i = 0, memrec.Count-1 do memrec[0].destroy() end Если проще руками забить и поставить опцию раскрытия, то можно и без скрипта.
  • Сделать большой брейкпоинт на структуру через dbk_useKernelmodeOpenProcess

    Перенесена Статьи и видео фишки breakpoint ce lua dbk
    3
    4
    0 Голоса
    3 Сообщения
    209 Просмотры
    MasterGHM
    Пользователь @Pitronic написал в Сделать большой брейкпоинт на структуру через dbk_useKernelmodeOpenProcess: Мы знаем что адрес таймера на выстрел во первых лежит в одной структуре с патронами, во вторых адрес в начале меняется в момент выстрела одновременно с уменьшением патронов и в пределах от одной до 100 миллисекунд возвращается в прежнее значение. может lua скрипт специальный можно сделать? Я бы сделал без скриптов. делаешь dessect structure Далее как обычно. Создаешь структуру. Затем вот это (следить за изменениями) ну а дальше воспроизводишь свой выстрел потом создаешь структуру из изменившихся данных (потому что их будешь очень много наверняка) затем делаешь lock на структуру, чтобы значения зафиксирвать затем рядом создаешь второй ряд по ctrl +a и смотрим изменения в реальном времени (игра должна быть в оконном режим, чтобы мы видели как цифры скачут) чтобы увидеть изменения менее 100мс нужно поставить интервал меньше По идее это должно сработать
  • Поиск по формуле

    Перенесена Статьи и видео фишки идея scan memory ce lua
    1
    7
    0 Голоса
    1 Сообщения
    82 Просмотры
    MasterGHM
    В таблице поиска есть колонки ссылающиеся на название Lua перменных: "value" и "previousvalue" Сравнивать текущее и предыдущие значения вместе или по отдельности, в том числе на разных вкладках CE Примеры: value == 65 value == 0x65 (или поставить галку hex) value ~= 65 (или поставить галку not) Можно и такое сравнение сделать после поиска неизвестного используя математические функции: math.abs(value - previousvalue) < 10 Можно делать различные комбинации: and (логическое И). or (логическое ИЛИ). not (логическое НЕ). \+ (сложение); \- (вычитание); * (умножение); / (деление); ^ (возведение в степень); % (остаток от деления). == (равно); ~= (не равно); < (меньше); > (больше); <= (меньше или равно); >= (больше или равно). Можно написать функцию xor function BitXOR(a,b)--Bitwise xor local p,c=1,0 while a>0 and b>0 do local ra,rb=a%2,b%2 if ra~=rb then c=c+p end a,b,p=(a-ra)/2,(b-rb)/2,p*2 end if a<b then a=b end while a>0 do local ra=a%2 if ra>0 then c=c+p end a,p=(a-ra)/2,p*2 end return c end А потом применяем даже отдельные функции как в этом примере "value > 0 and BitXOR(value, 100) " А может быть я хочу только 100 первых результатов function BitXOR(a,b)--Bitwise xor local p,c=1,0 while a>0 and b>0 do local ra,rb=a%2,b%2 if ra~=rb then c=c+p end a,b,p=(a-ra)/2,(b-rb)/2,p*2 end if a<b then a=b end while a>0 do local ra=a%2 if ra>0 then c=c+p end a,p=(a-ra)/2,p*2 end return c end valueCount = 0 function CheckCount100() valueCount = valueCount + 1 return valueCount <= 100 end CheckCount100() and value > 0 and BitXOR(value, 50) Также хочу добавить те адреса, которые предположительно являются указателями getAddressSafe('['..value..']')~=nil Или наоборот не являются указателями getAddressSafe('['..value..']')==nil Еще можно попробовать добавить 50 красных и 50 синих указателей в таблицу CE, но это уже задание кому интересно. Можно в теории сравнивать адреса со значениями известных адресов и даже с известными указателями, с метками. Но поиск может затянуться, если адресов очень много. Можно попробовать указать условие, что значение адреса должно находиться в X структуре или в её вероятных указателях. Или попробовать оставить только одинаковые значения адресов, т.е. повторяющихся более 1 раза. Или попробовать искать только те адреса, к которым применимы сразу несколько условий чтобы не кликать их постоянно: (изменилось) И (больше 0) И (меньше 10000) (не изменилось) И (больше 0) И (меньше 10000)
  • Медленный брейкпоинт

    Перенесена Статьи и видео breakpoint фишки идея
    1
    0 Голоса
    1 Сообщения
    663 Просмотры
    MasterGHM
    Если условный брейкпоинт очень часто выполняется и это приводит к очень сильным тормозам, то есть пара приемов Сделать АА скрипт, который проверяет условие cmp eax, [АДРЕС] jne x1 nop // здесь поставить на код брейкпоинт без условия x1: // здесь оригинальный код На инструкции проходит очень много адресов и окно с определяемыми адресами виснет. Теоретическое решение. Сделать АА скрипт, который через alloc() создаст блок памяти (буфер) для будущих адресов и их счетчиков. Через второй АА код сделать инъекцию, которая во время игры в буфер будет записывать не повторяющиеся адреса и повторяющиеся счетчики. Чтобы просмотреть результат можно зайти в MemoryView — просмотр памяти в CE. Области памяти также можно сравнивать в "Dessect Data" окне
  • Управление состояниями memory record

    Перенесена Статьи и видео ce aa ce memrec фишки
    1
    0 Голоса
    1 Сообщения
    98 Просмотры
    MasterGHM
    Перехватываем состояния у checkbox memory recrod (у записи в таблицы CE) и меняем состояние активации и деактивации по другим условиям {$lua} \-- прсто инфо memrec.OnActivate = function(record, before, currentstate) print("OnActivate"..(before and "Before " or "After ")..(currentstate and "true" or "false")) return true end \-- прсто инфо memrec.OnDeactivate = function(record, before, currentstate) print("OnDeactivate"..(before and "Before " or "After ")..(currentstate and "true" or "false")) return true end \-- подмена состояния function onMemRecPostExecute(memoryrecord, newState, succeeded) if memoryrecord == memrec and newState then print('Меня активировали, но я деактивируюсь сам') memrec.Active = false end end {$asm} [ENABLE] {$lua} print('Состояния сейчас '..(memrec.Active and "true" or "false")) print('Пишу в адрес [адрес..] ... (float)10000.0') {$asm} // написать свой адрес //[адрес..]: // dd (float)10000.0 // написать свой адрес //[адрес..]: // dd (float)10000.0 // написать свой адрес //[адрес..]: // dd (float)10000.0 [DISABLE]