CELua[RU]
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы
    • Зарегистрироваться
    • Войти
    1. Главная
    2. MasterGH
    3. Сообщения
    Не в сети
    • Профиль
    • Подписки 1
    • Подписчики 1
    • Темы 134
    • Сообщения 260
    • Группы 4

    Сообщения

    Последние Лучшие сообщения Спорные
    • RE: CE Tool Lua Regular expressions 2

      Lua поиск элемента до и после строки

      Была задача получить два списка из документа, в котором было с пару десятков тысяч строк. На практике выяснилось, что искать текст после ключевого слова легче чем искать текст до ключевого слова. Об этом и будет дальше

      В утилите "Lua Regular Expressions (v. 1.0)"
      image.png
      Текст во вкладке "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"

      написал в Плагин-строй
      MasterGHM
      MasterGH
    • CE Tool Lua Regular expressions 2

      CT таблица для составления регулярных выражений 4-х функций

      string.match (s, pattern [, init])
      string.gmatch (s, pattern)
      string.gsub (s, pattern, repl [, n])
      string.find (s, pattern [, init [, plain]])
      

      Функция string.gsub может принимать в аргумент функции "repl" таблицу (тогда будет замена по ключам значений из таблицы ) или в аргумент "repl" может попадать некоторая другая функция с аргументом найденного слова (тогда будет вызов этой другой функции при каждом захвате символа или слова). Более подробное в документации Lua 5.3

      Еще несколько ссылок с практическим руководством

      lua-users wiki: Sample Code
      lua-users wiki: Optimisation Tips
      lua-users wiki: Object Oriented Programming
      lua-users wiki: Tutorial Directory

      9c7cb7f1-e10d-4d07-84c5-6d2ee905e441-image.png

      63a3f6ae-ce5e-4d49-b556-534380157b0f-image.png
      2df0435b-b355-48e3-934a-00e4daa0dcca-image.png

      8f2a6a5e-2b4c-4d9a-b13d-17a80956faa8-image.png

      f23565ca-e4bb-4896-a680-54f00a0a2975-image.png

      написал в Плагин-строй ce plugin
      MasterGHM
      MasterGH
    • CE disassembler

      80185edf-e083-49a5-9ed3-dde77b9d94cf-image.png
      2c49f00f-7aad-453e-8131-196e0c918444-image.png

      Кратко

      1. Добавил сохранение/загрузку параметров. Хранение в текстовом файле в папке autoruns

      2. Добавил настройки графического интерфейса (слайдеры, пункт меню)

      3. Обновления UI

        • Гладкая перерисовка, двойной буфер
        • Стрелки прыжков сдвигаются вправо при увеличении их количества
        • Слайдер яркости фона
        • Слайдер количества адресов в невидимой области от 0 до +1К от верхнего и нижнего адресов. Увеличивает количество стрелок для прыжков.
        • Стрелки в невидимой области обозначаются двумя цветами.
          Один цвет для тех стрелок, у которых адрес прыжка и адрес назначения не выходят в область видимости.
          Второй цвет для тех стрелок, которых адрес прыжка или адрес назначения входят в области видимости.
          Видимые стрелки обозначаются белым.
          На рисуемые стрелки прыжков влияет слайдер яркости.
        • Не показывать стрелки прыжков для инструкций типа 'jmp [...]', 'jne [...]'...
      4. Сохранение и загрузка при заходе и выходе из CE

        • значения слайдеров
        • верхнего адреса
        • выбранного адреса
        • параметры шрифтов и других

      С цветами экспериментировал не понравилось, пока оставляю градацию "черный-белый".

      Основное назначение его показывать приоритетные инструкции более ярким цветом. Инструкции такие как арифметические и логические. Это первый и второй слайдеры. Третий - инструкции на запись, чтение. Четвертый - инструкции ветвления. Пятый слайдер - остальные инструкции. Остальные слайдеры связаны с настройками. Основные из них размер шрифта, яркость фона, вертикальный отступ между инструкциями и другие.

      Также в плагин встроена поддержка работы с окнами трейслогов.
      8de95150-d583-40ce-9bd0-f351c8ae3e6d-image.png

      Происходит постоянный поиск новых и отсутствующих окон трейслогов... Делаем трейслоги. Двойной клик по адресам и переходим по адресу в дизассемблер (если он открыт) и видим в нем раскрашенные пути маркерами. Если окон много, то видим пересечения, расхождения путей и видим инструкции, которые не выполнялись...Встроено контекстное меню установки брейкпоинтов на call-ы в трейслоге. Если его вызывать, то после идем в игру и, не делая того, что исследуем, прерываемся на брейкпоинтах и снимаем их. Когда больше не прерываемся, то делаем в игре то, что нужно и прерываемся на оставшемся брейкпоинте. На нем исследуем условие входа в рутину. Тут как бы можно на страх и риск изменить условие, чтобы ветка кода повторила свое выполнение. Если позволяет, то выполнить поток вызвав call... Но я придерживаюсь варианта изменения данных для того чтобы поток сам повторил рутину. Либо подменить параметры функции или подменить параметры после выхода функции. На данный момент показать что-то на практике нечего. Как будет, сделаю и покажу видео.

      Встроена поддержка маркирования путей на выбранном участке кода. Это специальное окно в меню "утилитах" в окне дизассемблера его можно найти. Указывается верхний адрес и нижний адрес области кода. Например, функции. При старте начинается логирование уникальных прохождения от начального до конечного адреса и раскраска маркерами. Возможных таких путей 8. Т.е. делая что-то в игре (разовые действия) видим уникальную ветвь, она тут же появляется и на этой ветви можно прерваться поставив опцию, и оттрейсить выход из рутины...

      Более подробное описание и скриншоты в закрытом разделе в моем старом блоге. Имеют к нему доступ пользователи со статусом "Разработчики". Новую информацию я буду писать в этой теме.

      Плагин сейчас на стадии чернового варианта, кто хочет пробуйте. Установка с репозитория. Чтобы подключить нужно загрузить .CT таблицу. Знаю что не удобно, но пока так.

      Плагин планируется развивать дальше, сейчас это черновой вариант

      написал в Плагин-строй ce plugin
      MasterGHM
      MasterGH
    • RE: CE Compact View

      Ниже находится обучающий пример плагина для 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.

      написал в Плагин-строй
      MasterGHM
      MasterGH
    • CE Compact View

      Функции

      1. Контекстное меню. Компактное/ не компактное окно CE
      2. Сохранение и загрузка положения и размера формы CE
      3. Сохранение и загрузка компактного состояния формы или не компактного

      После запуска, CE будет там, где её (CE) закрыли с позицией, размерами и с состоянием "Компактны режим", если последний был включен.

      Параметры сохраняются на жесткий диск в файл "..\autorun\userdata.txt"

      написал в Плагин-строй
      MasterGHM
      MasterGH
    • Поиск данных в окне Tracer
      \-- ищет адрес по адресу
      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
      
      написал в MasterGH tracer ce lua
      MasterGHM
      MasterGH
    • Функции для работы с адресами
      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)
      
      написал в MasterGH
      MasterGHM
      MasterGH
    • Пользовательские тип данных в hex-окне (пример)
      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)
      
      написал в MasterGH custom types
      MasterGHM
      MasterGH
    • Lua генерирует и исполняет код

      Функция 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
      
      написал в MasterGH loadstring генерация кода
      MasterGHM
      MasterGH
    • Часть1. Lua простые регулярные выражения

      Есть такой плагин "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 кода
      1d5685ba-4f64-4bf1-9eb3-8d9c82fdc34c-image.png

      Функции по работе со строками. Link

      Используемые источники: link, link, link, link

      aamaker.lua

      написал в Программирование ce lua regular
      MasterGHM
      MasterGH
    • Часть2. Lua простые регулярные выражения

      Если нужно найти начало и конец подстроки. Пример

      Попробуем найти слово 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 
      

      Пока на этом все... Более сложные примеры в предыдущей части записи

      написал в Программирование lua regular ce lua
      MasterGHM
      MasterGH
    • Notepad++ и CE Lua. Автозавершение строк

      7085e9b1-8d9f-4852-a51a-1a147d2d73ec-image.png
      Можно в редакторе сделать автозавершение инструкци для CE Lua и даже для CE Autoassembler.
      Накидал пример, может быть, кому интересно будет для других языков.
      Установка. Поместить файл в директорию на скриншоте
      lua.xml
      45d8a0ce-3f98-4e46-a5fe-277b6b95f63e-image.png
      5927bc47-eb33-4ce6-bf81-79f12af68497-image.png

      написал в MasterGH
      MasterGHM
      MasterGH
    • RE: Задачка по IDA и Python (старое)

      Пост принадлежит автору 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
      написал в MasterGH
      MasterGHM
      MasterGH
    • Задачка по IDA и Python (старое)

      Вдохновение появилось после просмотра видео по Ultimap
      Когда в Ultimap появляются Nx адресов с одним счетчиком, то хочется увидеть эти связи на графиках IDA. Появилась идея загуглить как в IDA через IDC скрипт отрисовать ветвь кода или ветви кода, на которых эти самые адреса связаны между собой, а все вложенные другие скрывать. Пока из подсказок я нашел это и это
      Допустим для тренировки даны два адреса из одной ветви кода (это я точно знаю, т.к. получен не из ultimap, а из tracelog)
      9b0dc013-27a6-43ad-a078-f8abaec91d20-image.png
      Адрес1 - Tutorial-i386.exe+2578F - 29 83 AC040000 - sub [ebx+000004AC],eax" или адрес 0x00402B77
      Адрес2 - Tutorial-i386.exe+16DBED - 89 45 FC - mov [ebp-04],eax или адрес 0x0056DBED

      И вот думаю, как скрипт ниже переделать, чтобы сначала вывести текстовый маршрут, а потом и хотя бы одну ветвь кода. Т.е. поднимаясь вверх по иерархии вызовов нужно остановиться до Адреса2.

      #include <idc.idc>
      	
      static main()
      {
      	auto ea, func, ref;
      	
      	// получаем текущий адрес курсора
      	ea = 0x00402B77;
      	
      	// в цикле от начала (SegStart) до конца (SegEND) текущего сегмента
      	for (func = SegStart(ea); func != BADADDR && func < SegEnd(ea); func = NextFunction(func))
      	{
      		// если текущий адрес является адресом функции
      		if (GetFunctionFlags(func) != -1)
      		{
      			Message("Function %s at 0x%x\n", GetFunctionName(func), func);
      			
      			// находим все ссылки на данную функцию и выводим
      			for (ref = RfirstB(func); ref != BADADDR; ref = RnextB(func, ref))
      			{
      				Message(" called from %s(0x%x)\n", GetFunctionName(ref), ref);
      			}
      		}
      	}
      }
      

      Пока просто вывод от стартовой функции без условий
      f65fbeba-c428-41c2-a94e-66127365ff72-image.png

      Как будет время попробую доделать...
      p.s. Ну ничего так idc скрипты. Много всего, но смысл тот же, что и в CE Lua у некоторых функций. Еще не разобрался как Python подключить к IDA, пока на idc скриптах.
      Будет интересно еще посмотреть эту же задачу на Hydra и Radare, ну и в CE (в новой версии появилось окно диаграмм)
      19dc87e2-46e1-4bf2-86a3-173ab2e2ed85-image.png

      написал в MasterGH
      MasterGHM
      MasterGH
    • Unity API (игровой движок)

      API

      написал в API
      MasterGHM
      MasterGH
    • Panda3D API (игровой движок)

      API

      API Reference — Panda3D Manual
      написал в API
      MasterGHM
      MasterGH
    • Frostbite API (игровой движок)

      API

      Frostbite API

      Блоги

      [Week 7] A Real Game Engine - Isetta Engine
      написал в API
      MasterGHM
      MasterGH
    • CryEngine API (игрвой движок)

      Изучив API, можно управлять иерархией сущностей, сценами, физикой и т.п. в играх созданных на этом движке.

      Игровой бинарный код будет состоять из функций игрового движка и функций разработчиков игры. Можно управлять сущностями на основе API движка или же функциями разработчиков.

      написал в API
      MasterGHM
      MasterGH
    • UnrealEngine API (игровой движок)

      UnrealEngine - популярный игровой движок с открытым API.

      Открытое API должно позволить управлять иерархией сущностей (акторы). Т.е. создать сущности, удалять, менять положение в иерархии. Управлять сценами с этими сущностями, физикой, Meshes, эффектами, звуками...

      Единственное нужно разобраться в этом API, собрать dll модуль на языке программирования и загрузить его в игру... ну, и возможно, управлять этим модулем извне.

      написал в API
      MasterGHM
      MasterGH
    • Windows API

      API Windows - это пользовательские функции для работы с процессами и памятью. Все программы, приложения, сервисы, в том числе и программа CE используют эти функции и даже игры. Функции что-то делают, что-то вызывают, какие-то результаты возвращают. Смотрим справки

      Win32.chm - справочник

      Другие ресурсы:

      Справочник по Windows API
      Вызов функций Windows API
      Основы программирования для Win32 API

      Софт для работы с API:

      API Monitor: Spy on API Calls and COM Interfaces (Freeware 32-bit and 64-bit Versions!) | rohitab.com
      https://sematext.com/blog/api-monitoring-tools/[Win32.chm](/assets/uploads/files/1683990989161-win32.chm)

      Книги:
      Книга "[RU] Джефри Рихтер Windows для профессионалов. 4 издание.pdf"

      написал в API
      MasterGHM
      MasterGH
    • 1 / 1