• Tool C# Regular Expression

    Перенесена Вопросы, обсуждения и предложения
    1
    1
    0 Голоса
    1 Сообщения
    109 Просмотры
    MasterGHM
    Regular Expression.rar string allText = richTextBox1.Text; string pattern = textBox2.Text; string s = string.Empty; try { Regex regex = new Regex(pattern); MatchCollection matches = regex.Matches(allText); if (matches.Count > 0) { foreach (Match match in matches) s += match.Value + ";\r\n"; } else { s = "Совпадений не найдено"; } textBox3.Text = s; } catch (Exception) { //throw; }
  • CE mapbranches

    CE Plugins
    1
    4
    0 Голоса
    1 Сообщения
    774 Просмотры
    MasterGHM
    MapBranches (Другие записи: https://celua.ru/topic/113/ветвления-кода-связанные-с-адресом-старые-записи/2) На адрес устанавливается брейкпоинт. Идем в игру делаем или не делаем что-то Начинают срабатывать инструкции на брейкпоинте От каждой инструкции начинается трейслог, подобный тому, который есть у CE, но менее тормозной Заканчивается трейслог на инструкции, на 100-ом счетчике после ret-а (об этом пункте будет уточнение). Здесь выходим на коневой цикл Трейслог останавливается и ожидание следующей инструкции, которая сработает на брейкпоинте, она должна быть отличной В итоге мы имеем кучу трейслогов начинающихся с адреса работающего с параметром (например, кол-во патронов в обойме) и заканчивающихся на корневом цикле. Также мы собираем данные об адресах с рет-ами и счетчиками. По этим данным можно нарисовать схему, где ret-ы меняют направление пути прохождения потоком дизассемблерного кода На скриншотах ниже Вертикальные линии со кружками -— это ветвь трейслога Белый кружок — адрес ret-a, который не повторялся Пунктирный кружок — адрес ret-а, который повторялся. Стрелка от такого пунктирного круга будет указывать на белый круг. По схеме видим, где ret-ы меняют свое направление поднимаясь по рутине в корневом цикле По плану по визуальной части: Клик на кружок — переход на код Придумать что-то, чтобы стрелки не накладывались друг на друга Установка брейкпоинтов на кружках — становиться красными Легенда. Номер ветви, связанная инструкция, состояние брейкпоинтов. Комментарий к ветви Загрузка/сохранение легенды Для чего нужно. Для поиска условий, которые включают и выключают ветви кода. Т.е. чтобы можно было это условие быстро найти и изменив его, повторить выполнение кода ветви, которая "пробьётся" из корневого цикла. Таким образом попытаться повторить действие в игре, а если не получаться повторить, то определить дополнительные условия.
  • Ветвления кода связанные с адресом (старые записи)

    Перенесена Вопросы, обсуждения и предложения
    2
    2
    0 Голоса
    2 Сообщения
    182 Просмотры
    MasterGHM
    Трассеровка по ретам ------- На скриншоте 22 ветви трассеровки от адреса патронов не входя в call-ы до корневого цикла. Корневой цикл определяется, когда поиск происходит более трех секунд и не находит ничего. Вполне хватает этого времени. Буду еще повторно тестить и проверять доходит ли он цикла или надо еще что-то придумывать. Желтым выделяется точка, вертикальная полоса ветви и связи с такими же узлами. Узел это адрес выхода из ret Внизу ряд счетчиков от 00 до 99. Если более 99 то отсчет заного. Показывает дианамику обращения к ветвям после нахождения корневого цикла Есть еще несколько функций, которых не видно на скриншоте — в контекстном меню. Анализ можно запустить из окна CE из главной таблицы, выделив адрес и опцию либо на чтение, либо на доступ. При тестах увидел, что логи неполные. Например, первый кружок это инструкция читающая патроны очень часто. От этой инструкции идут вверх множество вариантов ветвей,а у меня один вариант — вертикальная полоска с кружками. От первого круга надо сделать ветвление влево и вправо. Занялся модернизацией этого рисования и оптимизацией. Например, чтобы определить является ли проход по ret, то не нужен дизассемблер. Залез в доки и посмотрел опкоды function IsRet(address) local value = readBytes(address,1, false) return value == 0xC3 or value == 0xCB or value == 0xC2 or value == 0xCA end Скорость трассеровки должна в несколько раз увеличиться. К сожалению, смогу это узнать, когда перепишу текущий плагин. Там были уже сделаны изменения (все еще сырое для публикации плагина, пока не публикую) Нумерация ветвей Клик на круг — переход в дефоттный дизассемблер Подсвечивать выбранный круг Перерасчет позиций, когда поменялся размер окна Счетчики выполнений инструкций срабатывающих к обращению на адрес Изменен способ рисования связей между ветвями Контекстное меню Показать ветку Контекстное меню Скрыть ветку На скрытой ветви не показываются связи упрощая обзор. Код поднимается снизу вверх. Если одна ветвь ниже другой, то можно её скрыть. Ориентируемся по счетчикам хитов на инструкции Контекстное меню Сброс хитов Оптимизация поиска корневого цикла Выделение связей Оптимизация рисования новых свзей Контекстное меню пауза/продолжение Запуск из контекстного меню при выделеии адреса в главной таблице При закрытии окна снимаются все брейкпоинты Возможность ставить логи на запись из контекстного меню и на чтение в главной таблице CE
  • [CE Lua Plugin] Способ раскраски значений найденных адресов

    Перенесена Вопросы, обсуждения и предложения
    1
    1
    0 Голоса
    1 Сообщения
    67 Просмотры
    MasterGHM
    Пример раскрашивания адресов без каких-либо условий MainForm.Foundlist3.OnCustomDrawSubItem = function(sender, ListItem, SubItemIndex, state, DefaultDraw) if ListItem.Index % 3 == 0 then if SubItemIndex % 2 == 0 then sender.canvas.font.color = 0xff0000 else sender.canvas.font.color = 0x00ffff end else sender.canvas.font.color = 0xffff00 end return true end Из прошлой записи блога нашли "MainForm.Foundlist3" для работы с TListView (компонент от Lazarus среды разработки) OnCustomDrawSubItem — функция обработчик раскрашивания вложенных элементов в Item. Не поленитесь, зайдите в файл документации (C:\Program Files\Cheat Engine 7.4\celua.txt) Также есть OnCustomDrawItem — раскрашивание невложенных элементов. source Этот способ раскрашивания можно использовать по условиям. Чтобы связать условия с адресами и цветом смотри MemScan Class, FoundList class в celua.txt.
  • CE Tool Lua Regular expressions 2

    CE Plugins ce plugin
    2
    5
    0 Голоса
    2 Сообщения
    206 Просмотры
    MasterGHM
    Lua поиск элемента до и после строки Была задача получить два списка из документа, в котором было с пару десятков тысяч строк. На практике выяснилось, что искать текст после ключевого слова легче чем искать текст до ключевого слова. Об этом и будет дальше В утилите "Lua Regular Expressions (v. 1.0)" Текст во вкладке "gmatch" Game1 gameCompany DAU 53.21k -20% Game2 gameCompany DAU 20.35k -20% Поиск элемента после строки: "DAU "DAU%c%c(.-)%c%c" 53.21k;20.35k; Поиск элемента до строки: "%c%c(.-)gameCompany%c%c" (паттерн со двигом скобок для поиска предыдущей фразы) не прокатит для вывода списка игр над фразой gameCompany ;53.21k -20% Game2 ; Очевидно, можно сделать поиск по похожим фрагментам, которые идут последовательно сверху вниз. Cначала добавим первую пустую строку и видим повторяющиеся фрагменты "%c%cGame1%c%cgameCompany%c%c" пишем шаблон ".*%c%c(.-)%c%cgameCompany%c%c" и опять мимо Game1;53.21k -20% Game2; Потому что текст над Game2 пошел выше Game2. Тогда делаем захват, только первой фразы и дальше не идем "%c%c(%w-)%c%cgameCompany%c%c" Game1;Game2; И тогда все ок. Но это еще не все. Осталась первая пустая строка, которую добавили, если её удалить, тогда "%c%c(%w-)%c%cgameCompany%c%c" Game2; Не видит Game1. Значит мы можем убрать %c%c, и будет "(%w-)%c%cgameCompany" Game1;Game2; Дальше название игры может быть таким "My Game: my Game". Здесь и пробел и двоеточие. В таком случае текст уже будет My Game1: my Game gameCompany DAU 53.21k -20% My Game2: my Game gameCompany DAU 20.35k -20% Пробуем "(%w-)%c%cgameCompany" Game;Game; Что не верно, т.к. захват одним (%w-) Мы должны в скобках развернуть фразу имени игры. В ней могут быть пробелы, числа, текст и двоеточие '([%w%s]-)%c%cgameCompany' my Game; my Game; Затем ([:%w%s]-)%c%cgameCompany My Game1: my Game; My Game2: my Game; Затем %c?%c?([:%w%s]-)%c%cgameCompany My Game1: my Game; My Game2: my Game; Вот и все. Если попариться один раз, то тексты уже парсить будет гораздо быстрее. Так я вывел столбы DAU и названий игр в таблицу, что было в районе 500 строк из пару десятков тысяч строк p.s. Текст в консоли Lua отличается %c%c, а %с p.s.p.s. Можно раcсплитить текст по "/n/r" или "/n" в таблицу строк и по индексам данных находить предыдущую или последующую фразу. Но мне проще две строки ввести "%c?%c?([:%w%s]-)%c%cgameCompany" и "DAU%c%c(.-)%c%c"
  • CE disassembler

    CE Plugins ce plugin
    1
    3
    0 Голоса
    1 Сообщения
    732 Просмотры
    MasterGHM
    Кратко Добавил сохранение/загрузку параметров. Хранение в текстовом файле в папке autoruns Добавил настройки графического интерфейса (слайдеры, пункт меню) Обновления UI Гладкая перерисовка, двойной буфер Стрелки прыжков сдвигаются вправо при увеличении их количества Слайдер яркости фона Слайдер количества адресов в невидимой области от 0 до +1К от верхнего и нижнего адресов. Увеличивает количество стрелок для прыжков. Стрелки в невидимой области обозначаются двумя цветами. Один цвет для тех стрелок, у которых адрес прыжка и адрес назначения не выходят в область видимости. Второй цвет для тех стрелок, которых адрес прыжка или адрес назначения входят в области видимости. Видимые стрелки обозначаются белым. На рисуемые стрелки прыжков влияет слайдер яркости. Не показывать стрелки прыжков для инструкций типа 'jmp [...]', 'jne [...]'... Сохранение и загрузка при заходе и выходе из CE значения слайдеров верхнего адреса выбранного адреса параметры шрифтов и других С цветами экспериментировал не понравилось, пока оставляю градацию "черный-белый". Основное назначение его показывать приоритетные инструкции более ярким цветом. Инструкции такие как арифметические и логические. Это первый и второй слайдеры. Третий - инструкции на запись, чтение. Четвертый - инструкции ветвления. Пятый слайдер - остальные инструкции. Остальные слайдеры связаны с настройками. Основные из них размер шрифта, яркость фона, вертикальный отступ между инструкциями и другие. Также в плагин встроена поддержка работы с окнами трейслогов. Происходит постоянный поиск новых и отсутствующих окон трейслогов... Делаем трейслоги. Двойной клик по адресам и переходим по адресу в дизассемблер (если он открыт) и видим в нем раскрашенные пути маркерами. Если окон много, то видим пересечения, расхождения путей и видим инструкции, которые не выполнялись...Встроено контекстное меню установки брейкпоинтов на call-ы в трейслоге. Если его вызывать, то после идем в игру и, не делая того, что исследуем, прерываемся на брейкпоинтах и снимаем их. Когда больше не прерываемся, то делаем в игре то, что нужно и прерываемся на оставшемся брейкпоинте. На нем исследуем условие входа в рутину. Тут как бы можно на страх и риск изменить условие, чтобы ветка кода повторила свое выполнение. Если позволяет, то выполнить поток вызвав call... Но я придерживаюсь варианта изменения данных для того чтобы поток сам повторил рутину. Либо подменить параметры функции или подменить параметры после выхода функции. На данный момент показать что-то на практике нечего. Как будет, сделаю и покажу видео. Встроена поддержка маркирования путей на выбранном участке кода. Это специальное окно в меню "утилитах" в окне дизассемблера его можно найти. Указывается верхний адрес и нижний адрес области кода. Например, функции. При старте начинается логирование уникальных прохождения от начального до конечного адреса и раскраска маркерами. Возможных таких путей 8. Т.е. делая что-то в игре (разовые действия) видим уникальную ветвь, она тут же появляется и на этой ветви можно прерваться поставив опцию, и оттрейсить выход из рутины... Более подробное описание и скриншоты в закрытом разделе в моем старом блоге. Имеют к нему доступ пользователи со статусом "Разработчики". Новую информацию я буду писать в этой теме. Плагин сейчас на стадии чернового варианта, кто хочет пробуйте. Установка с репозитория. Чтобы подключить нужно загрузить .CT таблицу. Знаю что не удобно, но пока так. Плагин планируется развивать дальше, сейчас это черновой вариант
  • CE Compact View

    CE Plugins
    2
    0 Голоса
    2 Сообщения
    183 Просмотры
    MasterGHM
    Ниже находится обучающий пример плагина для CE Lua с установкой компактного режима применяя парадигму ООП — инкапсуляции. Для программирования плагинов на Lua могут пригодится приемы ООП. Это касается сущностей, их поведений и взаимодействий между ними. В данном примере CECompactView — описание класса на основе мета-таблицы и оно является сущностью. Функции класса — uncompact() и compact(), которые реализуют поведения этой сущности. Основной скрипт с описанием сущности можно поместить в отдельный файл .lua и далее можно кратко инициализировать сущность и управлять ей Например \-- Создание экземпляра класса через new() функцию, где аргументом является состояние компактный или некомпактный ce_compact_view = CECompactView:new(true) \-- Проверить состояние \--print(ce_compact_view:get_state() and 'Compact View Mode' or 'Full View Mode') \-- Установить компактный режим \--ce_compact_view:compact() \-- Установить не компактный режим \--ce_compact_view:uncompact() Сам класс или мета-таблица. \-- Класс инкапсулирующий поведения компактного состояния окна CE CECompactView = {} function CECompactView:new(state) local obj = {} -- Состояние компактное или нет: true или false obj.compact_mode = state -- Форма CE, где getMainForm — поддерживаемая функция CE и возвращает главную форму CE obj.form_ce = getMainForm() -- Получение элементов контекстного меню главной формы local menu_items = obj.form_ce.menu.items -- Создание нового контекстного меню с названием CompactView и именем ItemCompact obj.menu_item_compact = createMenuItem(menu_items) obj.menu_item_compact.name = 'ItemCompact' obj.menu_item_compact.caption = 'CompactView' -- Добавление контекстного меню на главную форму menu_items.add(obj.menu_item_compact) -- Сменить состояние окна CE: компактное или нет function obj:set(state) -- view_components состояния скрытия компонентов obj.compact_mode = state -- видимость компонентов обратна компактному режиму local view_components = not state obj.form_ce.panel1.visible = view_components obj.form_ce.panel4.visible = view_components obj.form_ce.panel5.visible = view_components obj.form_ce.Splitter1.visible = view_components -- Записать имя по состоянию obj.menu_item_compact.caption = state and 'Full View Mode' or 'Compact View Mode' -- Поставить обработчик по состоянию obj.menu_item_compact.onClick = state and obj.compact or obj.uncompact print(state and 'Compact View Mode' or 'Full View Mode') end -- Некопактное окно CE function obj:uncompact() obj:set(true) end -- Компактное окно CE function obj:compact() obj:set(false) end -- Состояние окна CE: компактное или нет function obj:get_state() return obj.compact_mode end -- Связь таблицы (смотрим докуметацию по Lua) setmetatable(obj, self) obj.__index = self -- Активировать состояние obj:set(state) -- Возвращает ссылку на экземпляр return obj end \------------ \-- Создание экземпляра класса ce_compact_view = CECompactView:new(true) \-- Проверить состояние \--print(ce_compact_view:get_state() and 'Compact View Mode' or 'Full View Mode') \-- Установить компактный режим \--ce_compact_view:compact() \-- Установить не компактный режим \--ce_compact_view:uncompact() Скрипт можно сохранить в Lua файл и добавить в папку autorun.
  • Поиск данных в окне Tracer

    Перенесена Вопросы, обсуждения и предложения tracer ce lua
    1
    0 Голоса
    1 Сообщения
    100 Просмотры
    MasterGHM
    \-- ищет адрес по адресу referencedAddress == 0x0165F8BC \-- ссылка на байты. Почему-то не работает. Ниже будет другой путь referencedBytes == dwordToByteTable(98) \-- сравнение по инструкции. В конце инструкции нужно ставить пробел instruction == "ret " \-- так будет искать все вхождения "mov" instruction:match("mov") Ну и более интересная версия перебора и одновременного выделения записей. Здесь нужно открыть окно "Трейсера" и рядом в Lua окне писать свои условия в функции "Compare()", "PrintData()", Selected() -- Поиск окна Трейслога function GetTTreeViewTracelogs() local max = getFormCount() for i=0, max-1 do if(getForm(i).ClassName == 'TfrmTracer') then return getForm(i) end end return nil end function FindTraceLogData() -- Нашли окно Трейслога tracerForm = GetTTreeViewTracelogs() -- Перебираем все записи for index=0, tracerForm.Count do -- Если запись пуста, то пропускаем if tracerForm.Entry[index] ~= nil then local entry = tracerForm.Entry[index] if Compare(entry) then Selected(entry, index) PrintData(entry,index ) end end end end \-- Можно свое условие addressEAX = 0x001FB780 function Compare(entry) return addressEAX == entry.context.EAX end function PrintData(entry) --print(tracerForm.Entry[index].instruction) print(disassemble(entry.context.RIP)) end function Selected(entry, index) tracerForm.lvTracer.Items[index].Selected = true end FindTraceLogData() Из документации по окну Tracer TfrmTracer class (Inheritance: Form->ScrollingWinControl->CustomControl->WinControl->Control->Component->Object) properties Count: integer - number of entries in the list selectionCount: integer - The number of selected entries Entry[index]: table - Information about each entry. Read only. (Index starts at 0) table is formatted as: { address: integer - address of the instruction instruction: string - disassembled instruction instructionSize: integer - bytesize of the instruction referencedAddress: integer - address the code references referencedData: bytearray - The bytes of the referenced data at the time of tracing context: contexttable - the state of the cpu when this instruction got executed (contains registers(EAX/RAX, ...), floating points(FP) and XMM values hasStackSnapshot: boolean - set to true if there is a stack entry selected: boolean - Set to true if the entry is selected } StackEntry[index]: bytearray - The stacksnapshot of that entry. Nil if not available methods \--------------------------------------------------- Treeview Class : (Inheritance: CustomControl->WinControl->Control->Component->Object) createTreeView(owner) properties Items: TreeNodes - The Treenodes object of the treeview (ReadOnly) Selected: TreeNode - The currently selected treenode methods beginUpdate() endUpdate() getItems() getSelected() setSelected() fullCollapse() : Collapses all the nodes, including the children's nodes fullExpand() : Expands all the nodes and all their children saveToFile(filename): Saves the contents of the treeview to disk \--------------- TreeNodes class : (Inheritance: TObject) properties Count : Integer - The total number of Treenodes this object has Item[]: TreeNode - Array to access each node [] = Item[] methods clear() getCount() getItem(integer) : Return the TreeNode object at the given index (based on the TreeView's Treenodes) add(text:string): Returns a new root Treenode object insert(treenode, string): Returns a new treenode object that has been inserted before the given treenode insertBehind(treenode, string): Returns a new treenode object that has been inserted after the given treenode \--------------- TreeNode class : (Inheritance: TObject) properties Text: string - The text of the treenode Parent: Treenode - The treenode this object is a child of. (can be nil) (ReadOnly) Level: Integer - The level this node is at HasChildren: boolean - Set to true if it has children, or you wish it to have an expand sign Expanded: boolean - Set to true if it has been expanded Count : Integer - The number of children this node has Items[]: Treenode - Array to access the child nodes of this node [] = Items[] Index: Integer - The index based on the parent AbsoluteIndex: Integer - The index based on the TreeView's Treenodes object (Items) Selected: Boolean - Set to true if currently selected MultiSelected: Boolean - Set to true if selected as well, but not the main selected object Data: Pointer - Space to store 4 or 8 bytes depending on which version of CE is used methods delete() deleteChildren() makeVisible() expand(recursive:boolean=TRUE OPTIONAL) : Expands the given node collapse(recursive:boolean=TRUE OPTIONAL) : collapses the given node getNextSibling(): Returns the treenode object that's behind this treenode on the same level add(text:string): Returns a Treenode object that is a child of the treenode used to create it ------------------------------------------ wordToByteTable(number): {} - Converts a word to a bytetable dwordToByteTable(number): {} - Converts a dword to a bytetable qwordToByteTable(number): {} - Converts a qword to a bytetable floatToByteTable(number): {} - Converts a float to a bytetable doubleToByteTable(number): {} - Converts a double to a bytetable extendedToByteTable(number): {} - Converts an extended to a bytetable stringToByteTable(string): {} - Converts a string to a bytetable wideStringToByteTable(string): {} - Converts a string to a widestring and converts that to a bytetable byteTableToWord(table, OPTIONAL signed:boolean): number - Converts a bytetable to a word byteTableToDword(table, OPTIONAL signed:boolean): number - Converts a bytetable to a dword byteTableToQword(table): number - Converts a bytetable to a qword byteTableToFloat(table): number - Converts a bytetable to a float byteTableToDouble(table): number - Converts a bytetable to a double byteTableToExtended(table): number - Converts a bytetable to an extended and converts that to a double byteTableToString(table): string - Converts a bytetable to a string byteTableToWideString(table): string - Converts a bytetable to a widestring and converts that to a string bOr(int1, int2) : Binary Or bXor(int1, int2) : Binary Xor bAnd(int1, int2) : Binary And bShl(int, int2) : Binary shift left bShr(int, int2) : Binary shift right bNot(int) : Binary not Для вывода referencedBytes из трейслога можно использовать byteTableToDword(referencedBytes) (смотрим документации выше) получая из TfrmTracer.Entry[index].referencedBytes или в строке поиска у Трейслога вбить byteTableToDword(referencedBytes) > 0 and print(string.format("0x%08X - 0x%08X", RIP, byteTableToDword(referencedBytes))) == 1
  • Функции для работы с адресами

    Перенесена Вопросы, обсуждения и предложения
    1
    0 Голоса
    1 Сообщения
    93 Просмотры
    MasterGHM
    disassemble(address): Disassembles the given address and returns a string in the format of "address - bytes - opcode : extra" splitDisassembledString(disassembledstring): Returns 4 strings. The address, bytes, opcode and extra field getInstructionSize(address): Returns the size of an instruction (basically it disassembles the instruction and returns the number of bytes for you) getPreviousOpcode(address): Returns the address of the previous opcode (this is just an estimated guess)
  • Пользовательские тип данных в hex-окне (пример)

    Перенесена Вопросы, обсуждения и предложения custom types
    1
    0 Голоса
    1 Сообщения
    68 Просмотры
    MasterGHM
    function bytes_to_value_function(b1,b2,b3,b4) -- для примера local table = {b1, b2, b3, b4} local dword = byteTableToDword(table) local refDataFromAddress = getAddressSafe(dword) if dataPointer ~= nil then return refDataFromAddress end return dword end function value_to_bytes_function(integer) -- просто для примера return bXor(integer, 100) end local isFloat = false registerCustomTypeLua('Pointer 2', 4, bytes_to_value_function, value_to_bytes_function, isFloat) Справка CustomType class (Object) The custom type is an convertor of raw data, to a human readable interpretation. global functions registerCustomTypeLua(typename, bytecount, bytestovaluefunction, valuetobytesfunction, isFloat) Registers a Custom type based on lua functions The bytes to value function should be defined as "function bytestovalue (b1,b2,b3,b4)" and return an integer as result The value to bytes function should be defined as "function valuetobytes (integer)" and return the bytes it should write returns the Custom Type object registerCustomTypeAutoAssembler(script) Registers a custom type based on an auto assembler script. The script must allocate an "ConvertRoutine" and "ConvertBackRoutine" returns the Custom Type object getCustomType(typename) : Returns the custom type object, or nil if not found properties name: string functiontypename: string CustomTypeType: TCustomTypeType - The type of the script script: string - The custom type script scriptUsesFloat: boolean - True if this script interprets it's user side values as float methods byteTableToValue({bytetable},Address Optional) valueToByteTable(value, Address Optional)
  • Lua генерирует и исполняет код

    Перенесена Вопросы, обсуждения и предложения loadstring генерация кода
    1
    0 Голоса
    1 Сообщения
    840 Просмотры
    MasterGHM
    Функция loadstring позволяет исполнять текст как код. Попробуем генерировать числа, сравнения чисел и логику И, ИЛИ. Цель: просто пример. Создать пары случайных чисел А и Б. Случайно сравнить попарно. Создать случайно логику "И, ИЛИ" и сравнить результаты сравнения до тех пор, пока не будут истинны function CheckTrue(parameter, strue, sfalse) if parameter then print(strue) else print(sfalse) end end ProgrammCompare_AxB = {} function ProgrammCompare_AxB:New(_name, _tableStringCondition) local obj = {} obj.programmName = _name obj.tableStringCondition = _tableStringCondition obj.stringCondition = '' obj.randomProgramm = '' function obj:MakeProgramm() obj.stringCondition = obj.tableStringCondition[math.random(1, #obj.tableStringCondition)] print(obj.stringCondition) obj.randomProgramm = 'function ' ..obj.programmName..'(a, b) return a '..obj.stringCondition..' b end' end function obj:RunProgramm(a, b) loadstring (obj.randomProgramm)() result = nil loadstring (string.format('result = %s(%s,%s)', obj.programmName, a, b))() CheckTrue ( result, string.format('a = %s, b = %s, result = true', a, b), string.format('a = %s, b = %s, result = false', a,b) ) return result end setmetatable(obj, self) obj.__index = ProgrammCompare_AxB return obj end compareProgramm1 = ProgrammCompare_AxB:New('ProgrammCompare_AxB_1', { '>', '<', '>=', '<=', '==', '~=' }) compareProgramm2 = ProgrammCompare_AxB:New('ProgrammCompare_AxB_2', { 'and', 'or' }) repeat compareProgramm1:MakeProgramm() compareProgramm2:MakeProgramm() -- Подбирать значения local a = compareProgramm1:RunProgramm(math.random(1, 100), math.random(1, 100)) local b = compareProgramm1:RunProgramm(math.random(1, 100), math.random(1, 100)) local c = compareProgramm2:RunProgramm(a, b) until c Пример вывода в Cheat Engine: >= or a = 83, b = 75, result = true a = 18, b = 86, result = false a = true, b = false, result = true Т.е. (83 >= 75 or 18 >= 86) == true, т.к. первое условие верное 83 >= 75 83 >= 75 = true 18 >= 86 = false
  • Как контролировать включение и выключение скриптов в таблице

    Перенесена Статьи и видео ce lua условие управление
    1
    0 Голоса
    1 Сообщения
    112 Просмотры
    MasterGHM
    Как контролировать включение и выключение скриптов в таблице AA или "Autoassembler code" код похожий на язык программирования ассемблера. Кратко, он позволяет менять игровой код. Подробнее Cheat Engine:Auto Assembler (http://wiki.cheatengine.org/index.php?title=Cheat_Engine:Auto_Assembler) Обычный АА-скрипт состоит из двух директив и добавляется в таблицу CE как запись // Код срабатывающий как при активации, так и при деактивации [ENABLE] // Код активации [DISABLE] // Код деактивации Чтобы код активировался, нужно включить галку напротив записи в таблице и наоборот выключить. Есть такие директивы как {$lua} и {$asm}. Под {$lua} пишут Lua скрипт, под {$asm} пишут АА-скрипт. Мы можем проверить Lua скриптом любое условие и разрешить включать галку или выключать галку. Например, через "syntaxcheck" — проверку синтаксиса или другое условие . Если проверка не прошла, то не получится галку включить и не получится выключить, если что-то пойдет не так. В Lua строка из двух минусов "--", обозначает комментарий. {$lua} \-- Расскоментируйте или закоментируйте пару строк ниже \-- if syntaxcheck then return end \-- error[666] = 666 \------------------------------ ENABLE ------------------------------ [ENABLE] \-- Расскоментируйте или закоментируйте пару строк ниже \-- if syntaxcheck then return end \-- error[666] = 666 \------------------------------ DISABLE ------------------------------ [DISABLE] \-- Расскоментируйте или закоментируйте пару строк ниже \-- if syntaxcheck then return end \-- error[666] = 666 Попробовав разные варианты вы увидите, что нельзя включать или выключать галку в разных ситуациях. Например в этой получится включить галку, а выключить нет из-за ошибки. {$lua} \-- if syntaxcheck then return end \-- некоторый lua код правильный или не правильный \-- error[666] = 666 \------------------------------ ENABLE ------------------------------ [ENABLE] \--if syntaxcheck then return end \-- некоторый lua код \-- некоторый lua код правильный или не правильный \-- error[666] = 666 \------------------------------ DISABLE ------------------------------ [DISABLE] if syntaxcheck then return end \-- некоторый lua код \-- некоторый lua код правильный или не правильный error[666] = 666 Следующий вариант проверяет открыт ли процесс. Если нет, то покажет сообщение. Как узнать, что процесс был закрыт после открытия process - зарезервированное переменная, показывает что процесс открыт (http://wiki.cheatengine.org/index.php?title=Lua:process) В комментариях можно увидеть при каких условиях блокируются включение галки {$lua} -- code before either enable/disable section runs for both just like with AA code if syntaxcheck then return end [ENABLE] if process == nil then showMessage('Процесс не подключен. Галка не будет включена') return end if process ~= nil and readInteger(process) == nil then showMessage('Процесс был закрыт. Галка не будет включена') return end [DISABLE] -- Галку можно выключить, но код выключения выполнять если процесс подключен if process ~= nil and readInteger(process) ~= nil then print('Attached to ' .. process) else showMessage('The process closed') end
  • Часть1. Lua простые регулярные выражения

    Перенесена Статьи и видео ce lua regular
    1
    1
    0 Голоса
    1 Сообщения
    215 Просмотры
    MasterGHM
    Есть такой плагин "AA Maker" и там довольно интересные регулярные выражения на Lua. Разберем некоторые выражения Выражение ''%[(.*)%]' - захват всего, что в квадратных скобках Пример local s = 'mov eax, [ecx + 4]' print(string.match(s, '%[(.*)%]')) \--> ecx + 4 Символ "%" нужно всегда ставить перед специальными символами такими как ^$()%.[]*+-? Символ "%[" и "%]" означают квадратные скобки в строке Разбирая комбинацию (.*). Точка означает любой символ, а символ умножить означает повторение любого символа Круглые скобки означают "подшаблон" Подшаблоны В шаблон можно включить подшаблоны, выделив их круглыми скобками. Если найденная строка соответствует шаблону, то ее подстроки, соответствующие подшаблонам, будут доступны для будущего использования. Подшаблоны пронумерованы согласно их левым круглым скобкам. Например, в шаблоне "(a*(.)%w(%s*))", часть строки, соответствующая "a*(.)%w(%s*)" будет зафиксирована как первый подшаблон (и поэтому имеет номер 1); любые символы попавшие под соответствие "." будут зафиксированы как подшаблон номер 2, и часть строки, соответствующая "%s*" получит номер 3. Специальный вариант использования подшаблонов - получение текущей позиции в строке. Для этого используются пустые подшаблоны (). Например, если мы применим шаблон "()aa()" к строке "flaaap", то получим два результата: 3 и 5. Шаблон не может содержать вложенные ноли. Используйте %z вместо этого. Т.е. можем извлечь содержимое инструкции. Примеры "(.*)" - захват всей строки "/(.*)/" - захват всего, что находится между КРАЙНИМИ символами / "/(.-)/" - захват всего, что находится между ПЕРВЫМИ ДВУМЯ символами / Пример из ААMaker плагина local _,_,x = string.find(opcode, '%[(.*)%]') из функции ниже Функция string.find("СТРОКА", "ШАБЛОН") возвращает номер позиции начала начала и конца шаблона Пример print(string.find('some string', 'me')) \--> 3 4 Вся функция с комментариями из AAMaker \-- Таблица паттернов для нескольких инструкций inc, mov, fld, fstp (ключи таблицы) \-- Они нужны для создания автоматического АА кода, через замену строк другими строками \- {$Type} — очевидно для типа byte, word, dword \- [x] — очевидно обращение к адресу \- {$Value} — это значение \- \r\n — переход на следующую строку \-- Что будем делать с этой таблицой будет видно по коду или смотрите плагин 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\n'..'mov{$Type}[x],{$Value}' } \-- Не очень понятно зачем квадратные скобки у ключей. Можно написать не ['inc'], а 'inc' \-- Функция проверки паттерна function checkPattern() -- Получение имени адреса из адреса dv_address1 (выделенный адрес в дизассемблере) local address = getNameFromAddress(dv_address1) -- Получение инструкции по имени адреса local _,opcode = splitDisassembledString(disassemble(address)) -- ComboBox.Text свойство равно "Injection" или "AOBScanModule" local choose = getProperty(cmbCheatType,"Text") if choose == 'Injection' or choose == 'AOBScanModule' then -- Перебор по ключу и значению таблицы PATTERN for key,value in pairs(PATTERN) do -- Если в опкоде нашли ключ из таблицы паттернов -- Где key это inc, mov, fld, fstp (см. выше таблицу PATTERN) -- Где opcode это например инструкция 'inc [edx + 4]' if string.find(opcode,key) ~= nil then local _,_,x = string.find(opcode, '%[(.*)%]') if x ~= nil then -- В value будет значение 'mov{$Type}[x],{$Value}' patternInjectAsmCode = value -- Нашли паттерн и вернули его return true end end end end -- Паттерн не нашли в таблице, вернули false patternInjectAsmCode = '{$OriginalCode}' return false end \-- patternInjectAsmCode Чтобы посмотреть результат, сделал скрин отладки Lua кода Функции по работе со строками. Link Используемые источники: link, link, link, link aamaker.lua
  • Часть2. Lua простые регулярные выражения

    Перенесена Статьи и видео lua regular ce lua
    1
    0 Голоса
    1 Сообщения
    128 Просмотры
    MasterGHM
    Если нужно найти начало и конец подстроки. Пример Попробуем найти слово lab в троке gamehacklab.ru print(string.find('gamehacklab.ru', 'lab')) >9 11 Если не найдена подстрока, то вернет nil. С помощью string.match можем выводить не индексы, а строку print(string.match('gamehacklab.ru', 'lab')) >lab С помощью string.gmatch можем выводить последовательно строки Где 'a.' означает символ 'a' и еще один следующий любой local result = string.gmatch('gamehacklab.ru', 'a.') print(result()) print(result()) print(result()) вывод >am >ac >ab Здесь комбинация символов "%a+" означает искать слово пока оно не закончится s = "hello world from Lua" for w in string.gmatch(s, "%a+") do print(w) end Вывод > hello > world > from > Lua А здесь заполняем таблицу ключ — значение из строки, которую можно было бы взять из файла t = {} s = "X=0, Y=0, Z=0" for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k] = v end for i, v in pairs(t) do print(i..' = '..v) end Вывод >Z = 0 >X = 0 >Y = 0 Пока на этом все... Более сложные примеры в предыдущей части записи
  • Notepad++ и CE Lua. Автозавершение строк

    Перенесена Вопросы, обсуждения и предложения
    1
    3
    0 Голоса
    1 Сообщения
    65 Просмотры
    MasterGHM
    Можно в редакторе сделать автозавершение инструкци для CE Lua и даже для CE Autoassembler. Накидал пример, может быть, кому интересно будет для других языков. Установка. Поместить файл в директорию на скриншоте lua.xml
  • Задачка по IDA и Python (старое)

    Перенесена Вопросы, обсуждения и предложения
    2
    3
    0 Голоса
    2 Сообщения
    154 Просмотры
    MasterGHM
    Пост принадлежит автору partoftheworlD, GamehackLab[RU]. (ref) Подключение к питону происходит с помощью: import idc import idautils import idaapi У меня есть наработки некоторые, возможно что-то пригодится. import idc import idaapi class Func(object): def __init__(self): self.reg_value = re.compile(r'') self.stack_view = [] self.level = 1 def range_reverse(self, start, stop): for i in FuncItems(stop): if start > i >= stop: yield i def run(self): if self.stack_view: for j in self.stack_view: current_function = idaapi.get_func(j) level = "-" * self.level print("{} Jump into -> 0x{}".format(level, hex(current_function.startEA)[2:].replace("L", "").upper())) for j in [i for i in self.range_reverse(current_function.endEA, current_function.startEA)]: print("{} 0x{} -- {}".format(level, hex(j)[2:].replace("L", "").upper(), idc.GetDisasm(j))) self.level += 1 else: print "Please input addresses to stack view buffer" pass if __name__ == '__main__': f = Func() f.stack_view = [0x214FE, 0x20F30, 0x214E0, 0x13F00] f.run() В выводе получим \- Jump into -> 0x214E0 \- 0x214E0 -- push ebp \- 0x214E1 -- mov ebp, esp \- 0x214E3 -- lea esp, [esp-10h] \- 0x214E7 -- mov [ebp+var_C], eax \- 0x214EA -- mov [ebp+var_4], edx \- 0x214ED -- mov [ebp+var_8], ecx \- 0x214F0 -- mov eax, [ebp+arg_0] \- 0x214F3 -- test eax, eax \- 0x214F5 -- jnz locret_21589 \- 0x214FB -- mov eax, [ebp+var_8] \- 0x214FE -- cmp word ptr [eax], 1Bh \- 0x21503 -- jnz locret_21589 \- 0x21509 -- push 0 \- 0x2150B -- mov eax, [ebp+var_8] \- 0x2150E -- movzx ecx, word ptr [eax] \- 0x21511 -- mov eax, [ebp+var_4] \- 0x21514 -- mov edx, 0B01Eh \- 0x21519 -- call sub_8E870 \- 0x2151E -- test eax, eax \- 0x21520 -- jnz short locret_21589 \- 0x21522 -- push 0 \- 0x21524 -- mov eax, [ebp+var_4] \- 0x21527 -- mov ecx, 0 \- 0x2152C -- mov edx, 87h ; '‡' \- 0x21531 -- call sub_8E870 \- 0x21536 -- and eax, 4 \- 0x21539 -- jnz short locret_21589 \- 0x2153B -- mov eax, [ebp+var_C] \- 0x2153E -- test dword ptr [eax+160h], 4 \- 0x21548 -- jz short locret_21589 \- 0x2154A -- mov eax, [ebp+var_4] \- 0x2154D -- mov dl, 1 \- 0x2154F -- call sub_13F00 \- 0x21554 -- mov [ebp+var_10], eax \- 0x21557 -- test eax, eax \- 0x21559 -- jz short locret_21589 \- 0x2155B -- mov eax, [ebp+var_10] \- 0x2155E -- cmp dword ptr [eax+378h], 0 \- 0x21565 -- jz short locret_21589 \- 0x21567 -- mov eax, [ebp+var_10] \- 0x2156A -- mov eax, [eax+378h] \- 0x21570 -- mov edx, [ebp+var_10] \- 0x21573 -- mov edx, [edx+378h] \- 0x21579 -- mov edx, [edx] \- 0x2157B -- call dword ptr [edx+2E8h] \- 0x21581 -- mov eax, [ebp+var_8] \- 0x21584 -- mov word ptr [eax], 0 \- 0x21589 -- leave \- 0x2158A -- retn 4 \-- Jump into -> 0x20F30 \-- 0x20F30 -- push ebp \-- 0x20F31 -- mov ebp, esp \-- 0x20F33 -- lea esp, [esp-10h] \-- 0x20F37 -- mov [ebp+var_C], eax \-- 0x20F3A -- mov [ebp+var_4], edx \-- 0x20F3D -- mov [ebp+var_8], ecx \-- 0x20F40 -- mov eax, [ebp+var_8] \-- 0x20F43 -- cmp word ptr [eax], 0 \-- 0x20F48 -- jz locret_20FCF \-- 0x20F4E -- mov edx, [ebp+var_4] \-- 0x20F51 -- mov eax, 5C29B4h \-- 0x20F56 -- call sub_C910 \-- 0x20F5B -- test al, al \-- 0x20F5D -- jz short loc_20FC3 \-- 0x20F5F -- mov eax, [ebp+var_4] \-- 0x20F62 -- mov [ebp+var_10], eax \-- 0x20F65 -- mov eax, [ebp+var_C] \-- 0x20F68 -- cmp word ptr [eax+150h], 0 \-- 0x20F71 -- jz short locret_20FCF \-- 0x20F73 -- mov eax, [ebp+var_C] \-- 0x20F76 -- mov edx, [ebp+var_8] \-- 0x20F79 -- mov ax, [eax+150h] \-- 0x20F80 -- cmp ax, [edx] \-- 0x20F83 -- jnz short locret_20FCF \-- 0x20F85 -- mov eax, [ebp+var_C] \-- 0x20F88 -- mov eax, [eax+154h] \-- 0x20F8E -- cmp eax, [ebp+arg_0] \-- 0x20F91 -- jnz short locret_20FCF \-- 0x20F93 -- mov eax, [ebp+var_C] \-- 0x20F96 -- mov eax, [eax+14Ch] \-- 0x20F9C -- cmp eax, [ebp+var_10] \-- 0x20F9F -- jnz short locret_20FCF \-- 0x20FA1 -- push [ebp+arg_0] \-- 0x20FA4 -- mov ecx, [ebp+var_8] \-- 0x20FA7 -- mov edx, [ebp+var_10] \-- 0x20FAA -- mov eax, [ebp+var_C] \-- 0x20FAD -- call sub_21590 \-- 0x20FB2 -- push [ebp+arg_0] \-- 0x20FB5 -- mov ecx, [ebp+var_8] \-- 0x20FB8 -- mov edx, [ebp+var_10] \-- 0x20FBB -- mov eax, [ebp+var_C] \-- 0x20FBE -- call sub_214E0 \-- 0x20FC3 -- mov eax, [ebp+var_C] \-- 0x20FC6 -- mov word ptr [eax+150h], 0 \-- 0x20FCF -- leave \-- 0x20FD0 -- retn 4 \--- Jump into -> 0x214E0 \--- 0x214E0 -- push ebp \--- 0x214E1 -- mov ebp, esp \--- 0x214E3 -- lea esp, [esp-10h] \--- 0x214E7 -- mov [ebp+var_C], eax \--- 0x214EA -- mov [ebp+var_4], edx \--- 0x214ED -- mov [ebp+var_8], ecx \--- 0x214F0 -- mov eax, [ebp+arg_0] \--- 0x214F3 -- test eax, eax \--- 0x214F5 -- jnz locret_21589 \--- 0x214FB -- mov eax, [ebp+var_8] \--- 0x214FE -- cmp word ptr [eax], 1Bh \--- 0x21503 -- jnz locret_21589 \--- 0x21509 -- push 0 \--- 0x2150B -- mov eax, [ebp+var_8] \--- 0x2150E -- movzx ecx, word ptr [eax] \--- 0x21511 -- mov eax, [ebp+var_4] \--- 0x21514 -- mov edx, 0B01Eh \--- 0x21519 -- call sub_8E870 \--- 0x2151E -- test eax, eax \--- 0x21520 -- jnz short locret_21589 \--- 0x21522 -- push 0 \--- 0x21524 -- mov eax, [ebp+var_4] \--- 0x21527 -- mov ecx, 0 \--- 0x2152C -- mov edx, 87h ; '‡' \--- 0x21531 -- call sub_8E870 \--- 0x21536 -- and eax, 4 \--- 0x21539 -- jnz short locret_21589 \--- 0x2153B -- mov eax, [ebp+var_C] \--- 0x2153E -- test dword ptr [eax+160h], 4 \--- 0x21548 -- jz short locret_21589 \--- 0x2154A -- mov eax, [ebp+var_4] \--- 0x2154D -- mov dl, 1 \--- 0x2154F -- call sub_13F00 \--- 0x21554 -- mov [ebp+var_10], eax \--- 0x21557 -- test eax, eax \--- 0x21559 -- jz short locret_21589 \--- 0x2155B -- mov eax, [ebp+var_10] \--- 0x2155E -- cmp dword ptr [eax+378h], 0 \--- 0x21565 -- jz short locret_21589 \--- 0x21567 -- mov eax, [ebp+var_10] \--- 0x2156A -- mov eax, [eax+378h] \--- 0x21570 -- mov edx, [ebp+var_10] \--- 0x21573 -- mov edx, [edx+378h] \--- 0x21579 -- mov edx, [edx] \--- 0x2157B -- call dword ptr [edx+2E8h] \--- 0x21581 -- mov eax, [ebp+var_8] \--- 0x21584 -- mov word ptr [eax], 0 \--- 0x21589 -- leave \--- 0x2158A -- retn 4 \---- Jump into -> 0x13F00 \---- 0x13F00 -- push ebp \---- 0x13F01 -- mov ebp, esp \---- 0x13F03 -- lea esp, [esp-0Ch] \---- 0x13F07 -- mov [ebp+var_4], eax \---- 0x13F0A -- mov [ebp+var_8], dl \---- 0x13F0D -- jmp short loc_13F33 \---- 0x13F10 -- cmp [ebp+var_8], 0 \---- 0x13F14 -- jnz short loc_13F27 \---- 0x13F16 -- mov edx, [ebp+var_4] \---- 0x13F19 -- mov eax, 59ECF0h \---- 0x13F1E -- call sub_C910 \---- 0x13F23 -- test al, al \---- 0x13F25 -- jnz short loc_13F45 \---- 0x13F27 -- mov eax, [ebp+var_4] \---- 0x13F2A -- mov eax, [eax+1F8h] \---- 0x13F30 -- mov [ebp+var_4], eax \---- 0x13F33 -- cmp [ebp+var_4], 0 \---- 0x13F37 -- jz short loc_13F45 \---- 0x13F39 -- mov eax, [ebp+var_4] \---- 0x13F3C -- cmp dword ptr [eax+1F8h], 0 \---- 0x13F43 -- jnz short loc_13F10 \---- 0x13F45 -- mov edx, [ebp+var_4] \---- 0x13F48 -- mov eax, 59ECF0h \---- 0x13F4D -- call sub_C910 \---- 0x13F52 -- test al, al \---- 0x13F54 -- jz short loc_13F5E \---- 0x13F56 -- mov eax, [ebp+var_4] \---- 0x13F59 -- mov [ebp+var_C], eax \---- 0x13F5C -- jmp short loc_13F65 \---- 0x13F5E -- mov [ebp+var_C], 0 \---- 0x13F65 -- mov eax, [ebp+var_C] \---- 0x13F68 -- leave \---- 0x13F69 -- retn Надо будет поправить пару строк, чтобы выводилась не функция целиком, а как при трассировке: for j in [i for i in self.range_reverse(current_function.endEA, current_function.startEA)]: https://raw.githubusercontent.com/EiNSTeiN-/idapython/master/examples/ex_graph.py
  • Unity API (игровой движок)

    Перенесена Справочники
    1
    0 Голоса
    1 Сообщения
    112 Просмотры
    MasterGHM
    API
  • Panda3D API (игровой движок)

    Перенесена Справочники
    1
    0 Голоса
    1 Сообщения
    70 Просмотры
    MasterGHM
    API API Reference — Panda3D Manual
  • Frostbite API (игровой движок)

    Перенесена Справочники
    1
    0 Голоса
    1 Сообщения
    76 Просмотры
    MasterGHM
    API Frostbite API Блоги [Week 7] A Real Game Engine - Isetta Engine
  • CryEngine API (игрвой движок)

    Перенесена Справочники
    1
    0 Голоса
    1 Сообщения
    81 Просмотры
    MasterGHM
    Изучив API, можно управлять иерархией сущностей, сценами, физикой и т.п. в играх созданных на этом движке. Игровой бинарный код будет состоять из функций игрового движка и функций разработчиков игры. Можно управлять сущностями на основе API движка или же функциями разработчиков.