Skip to content
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Collapse
Brand Logo

CELua[RU]

  1. Главная
  2. Программирование
  3. Создать структуру программно

Создать структуру программно

Запланировано Прикреплена Закрыта Перенесена Программирование
ce structurece lua
2 Сообщения 1 Posters 33 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • MasterGHM Не в сети
    MasterGHM Не в сети
    MasterGH Администраторы
    написал в отредактировано MasterGH
    #1

    Создать структуру программно

    Пример, что будет в конце записи
    изображение.png
    Нужен поинтер и процесс.

    Запустим туториал из Cheat Engine из меню Health->Cheat Engine Tutorial.
    Прохождение туториала подробно описано здесь

    Cheat Engine Tutorial Guide (x32) - Cheat Engine
    Подключаемся к процессу идем на 8-мой шаг. В руководстве есть поинтер
    [[[["Tutorial-i386.exe"+XXXXXX]+C]+14]+0]+18
    Вместо XXXXXX может быть любое смещение. Поэтому надо бы поискать

    Нашил адрес.
    Поставили бряк.
    Нашли esi
    Поставили бряк

    Вышли сюда

    0042595E - A1 60D65F00 - mov eax,[005FD660] { [0183E9E8] }
    00425963 - 8B 40 0C - mov eax,[eax+0C]
    00425966 - 8B 40 14 - mov eax,[eax+14]
    00425969 - FF 30 - push [eax]
    //...
    00425F3C - 89 46 18 - mov [esi+18],eax

    // Вот такой получили поинтер
    [[[[005FD660]+C]+14]+0]+18
    Поинтер получили, дальше пойдет Lua.

    Открываем Lua консоль и проверяем поинтер

    Выведем адрес и его значение

    \-- getAddress позволяет получить адрес. Если есть квадратные скобки, то и значение адреса
      local address = getAddress("[[[[005FD660]+C]+14]+0]+18")
      local value = getAddress("[[[[[005FD660]+C]+14]+0]+18]")
      local text = string.format('%X = %s',address,value)
      -- Показать диалог. В defines.lua можно посмотреть переменные mtInformation, mbok
      messageDialog(text, mtInformation, mbok)
      --> Вывод "018250E0 = 3289"
    

    Поинтер верный.

    Другой вариант читать значение поинтера примерно такой

    local address = getAddress("game.exe")
      address = readPointer(address + 0x123)
      address = readPointer(address + 0x456)
      local value = readFloat(address + 0x789)
    

    Есть и такие варианты

    value = readInteger("[[[[[[[[[witcher3.exe + 028F3F60] +0] +18] +20] +40] +40] + 1c0] +10] +28]")    
    value = readFloat("[[[[[[[[[witcher3.exe + 028F3F60] +0] +18] +20] +40] +40] + 1c0] +10] +28]")    
    value = readDouble("[[[[[[[[[witcher3.exe + 028F3F60] +0] +18] +20] +40] +40] + 1c0] +10] +28]")
    

    Теперь самое интересное — создание структур с помощью Lua
    Построим структуру [[[[005FD660]+C]+14]+0]+18. На +18 будет наш адрес.
    Сначала построим один уровень —"005FD660"

    \--Создаем пустую структуру и добавляем её в глобальный список
      myStructure = createStructure('MyStructure')
      myStructure.addToGlobalStructureList()
      -- Автоматически заполняем
      -- Праметры структуры: адрес, смещение и размер
      myStructure.autoGuess('005FD660', 0, 4096)   
      -- Создать окно и внести поле адреса
      local structureFrm = createStructureForm('005FD660')
      -- Выбрать структуру на форме. Через UI клик по индексу последней созданной структуры
      local structureIndex = getStructureCount() - 1
      structureFrm.Menu.Items[2][structureIndex+2].doClick()
    

    Если выполнить скрипт выше, то мы построим структуру одного уровня.
    Построим теперь структуру двух уровней "[005FD660]+C". Второй уровень нужно развернуть
    Для этого после создания структуры создам дочернюю

    myStructure2 = createStructure('MyStructure2')
      myStructure2.autoGuess('[005FD660]', 0, 50)
      -- И поместим её по индексу
      local offset = 0
      myStructure.getElementByOffset(offset).setChildStruct(myStructure2)
      -- Чтобы развернуть список поитеров. К сожалению разворачивается только два уровня
      structureFrm.Menu.Items[1][6].doClick()
    

    Итого получается такой скрипт до второго уровня

    \-- Создаем пустую структуру и добавляем её в глобальный список
      myStructure = createStructure('MyStructure')
      myStructure.addToGlobalStructureList()
      -- Автоматически заполняем
      -- Праметры структуры: адрес, смещение и размер
      myStructure.autoGuess('005FD660', 0, 4096)
    \------------------
      myStructure2 = createStructure('MyStructure2')
      myStructure2.autoGuess('[005FD660]', 0, 50)
    
      local offset = 0
      myStructure.getElementByOffset(offset).setChildStruct(myStructure2)
    \------------------
      -- Создать окно и внести поле адреса
      local structureFrm = createStructureForm('005FD660')
      -- Выбрать структуру на форме. Через UI клик по индексу последней созданной структуры
      local structureIndex = getStructureCount() - 1
      structureFrm.Menu.Items[2][structureIndex+2].doClick()
    
      structureFrm.Menu.Items[1][6].doClick()
    

    Создадим и развернем весь указатель [[[[005FD660]+C]+14]+0]+18
    Не будем делать через цикл, чтобы не усложнять

    myStructure2 = createStructure('MyStructure2')
      myStructure2.autoGuess('[005FD660]', 0, 50)
      local offset = 0x0
      myStructure.getElementByOffset(offset).setChildStruct(myStructure2)
    
      myStructure3 = createStructure('MyStructure3')
      myStructure3.autoGuess('[[005FD660]+C]', 0, 50)
      offset = 0xC
      myStructure2.getElementByOffset(offset).setChildStruct(myStructure3)
    
      myStructure4 = createStructure('MyStructure4')
      myStructure4.autoGuess('[[[005FD660]+C]+14]', 0, 50)
      offset = 0x14
      myStructure3.getElementByOffset(offset).setChildStruct(myStructure4)
    
      myStructure5 = createStructure('MyStructure5')
      myStructure5.autoGuess('[[[[005FD660]+C]+14]+0]', 0, 50)
      offset = 0x0
      myStructure4.getElementByOffset(offset).setChildStruct(myStructure5)
    

    Полный скрипт

    \-- Создаем пустую структуру и добавляем её в глобальный список
      myStructure = createStructure('MyStructure')
      myStructure.addToGlobalStructureList()
      -- Автоматически заполняем
      -- Праметры структуры: адрес, смещение и размер
      myStructure.autoGuess('005FD660', 0, 50)
    \------------------
      myStructure2 = createStructure('MyStructure2')
      myStructure2.autoGuess('[005FD660]', 0, 50)
      local offset = 0x0
      myStructure.getElementByOffset(offset).setChildStruct(myStructure2)
    
      myStructure3 = createStructure('MyStructure3')
      myStructure3.autoGuess('[[005FD660]+C]', 0, 50)
      offset = 0xC
      myStructure2.getElementByOffset(offset).setChildStruct(myStructure3)
    
      myStructure4 = createStructure('MyStructure4')
      myStructure4.autoGuess('[[[005FD660]+C]+14]', 0, 50)
      offset = 0x14
      myStructure3.getElementByOffset(offset).setChildStruct(myStructure4)
    
      myStructure5 = createStructure('MyStructure5')
      myStructure5.autoGuess('[[[[005FD660]+C]+14]+0]', 0, 50)
      offset = 0x0
      myStructure4.getElementByOffset(offset).setChildStruct(myStructure5)
    
      --[[[[005FD660]+C]+14]+0]+18
    \------------------
      -- Создать окно и внести поле адреса
      local structureFrm = createStructureForm('005FD660')
      -- Выбрать структуру на форме. Через UI клик по индексу последней созданной структуры
      local structureIndex = getStructureCount() - 1
      structureFrm.Menu.Items[2][structureIndex+2].doClick()
    
      structureFrm.Menu.Items[1][6].doClick()
    

    Результат
    33e4b026-502e-4ddd-809d-e1ca47ed7159-изображение.png

    Ну и на закуску.

    Допустим мы знаем что по адресу X будет всегда тип float (как X,Y,Z координаты). Но расструктуризация будет показывать другой тип, дизассемблер будет показывать другой тип — 4 байта. Что делать?

    И сразу еще допустим double тип всегда хотим как float тип (в виде комментов в дизассемблере или в расструктуризации)

    Воспользоваться следующей функцией

    -- Может менять тип адреса x в окне дизассемблере в комментариях, когда в инструкции существует адрес
    -- Может менять тип адреса в окне расструктуризации
    -- Изменив тип, будет ображаться значение другого типа
    onAutoGuess(function) :
    Registers an function to be called whenever autoguess is used to predict a variable type
    function override (address, ceguess): Return the variable type you want it to be. If no change, just return ceguess
    Ну и вот два примера

    
        -- Пример замена типа по типу
        function iKnowBetter1(address, ceguess)
            if (ceguess==vtDouble) then
              return vtDword
            else
              return ceguess
            end
          end
    
         -- Пример замена типа по адресу
        function iKnowBetter2(address, ceguess)  
          local someAddress = 0x1424AC6D0
          if (address == someAddress) then
            return vtSingle
          else
            return ceguess
          end
        end
    
        onAutoGuess(iKnowBetter1)
        onAutoGuess(iKnowBetter2)
    
    1 ответ Последний ответ
    0
  • MasterGHM Не в сети
    MasterGHM Не в сети
    MasterGH Администраторы
    написал в отредактировано
    #2

    Решил попробовать написать CE Lua скрипт, который прочесывает структуру и в Dissect data/structures окне создавал бы структуру только со смещениями, с которыми код работает, т.е. читает или пишет.

    Например, мой персонаж прогуливается по городу, а каждые 200 мс ставится брейкпоинт на смещение +1 до гипотетической N границы структуры (например до 4096).

    Я не успел сделать определение типа, но смещения внутри структуры получить я успел.

    Итак, находим начало структуры любой. Запускаем Lua скрипт и просто что-то делаем в игре. Потом вылазит текст с дизассемблированными инструкциями и смещениями. Уже по этим логам можно определить вручную

    1. к каким смещением было обращение (адреса по ним мы и будем менять или сравнивать структуры между собой позже)

    2. по виду инструкции и соседнему смещению уже примерно можно определить тип данных и их размер
      a3ea23e7-54e8-46c5-82a5-f3d2a73cc540-изображение.png
      Осталось сделать определение типа, а это не так уж долго сделать и осталось взять код из предыдущих записей в блоге формирования структуры в окне dessect data. Так мы получим структуру только с активными смещениями, (а зачем нам пассивные?) и определим в них тип, я надеюсь определим правильно

    Пример кода, который я использовал

    addressStructure1 = 0x412E0200 --> адрес начала структуры в любой игре
    sizeStructure = 100     --> гипототический размер структуры 100 для быстрых поисков, по умолчанию 4096
    indexStructure = 0      --> индекс внутри структуры, который будет перемещаться вместе с breakPointAddress
    breakPointAddress = 0   --> адрес, на который сейчас постален брейкпоинт
    waitTimeTillBreak = 300 --> частота активности смещеиня
    resultText = ''         --> конкатенация частей текста в этой переменной
    
    \-- Функция пытается поставить брейкпоинт на следующий байт в структуре
    function TryNextSetBreakPointToAddress()
      debug_removeBreakpoint(breakPointAddress)
      indexStructure = indexStructure + 1
      if indexStructure > sizeStructure then
        debugTimer.Interval = 1000
        debugTimer.Enabled = false
        debugTimer.destroy()
        debug_continueFromBreakpoint(co_run)
        print(resultText) --> вывод результата с завершением отладки
        return
      end
      breakPointAddress = addressStructure1 + indexStructure
      debug_setBreakpoint(breakPointAddress, 1, bptAccess, bpmDebugRegister)
      debug_continueFromBreakpoint(co_run)
    end
    
    \-- Любимая функция снятия отладочных данных
    function debugger_onBreakpoint()
      -- проверить обращение к структуре
      prevAddress = getPreviousOpcode(RIP)
      resultText = resultText..string.format('Offset: + %X : %s', indexStructure, disassemble(prevAddress)) .. '\r\n'
      TryNextSetBreakPointToAddress()
      return 1
    end
    
    \-- Простой таймер
    debugTimer = createTimer(nil, false)
    debugTimer.OnTimer = function(timer) TryNextSetBreakPointToAddress() end
    debugTimer.Interval = waitTimeTillBreak
    debugTimer.Enabled = true
    breakPointAddress = addressStructure1 + indexStructure
    debug_setBreakpoint(breakPointAddress, 1, bptAccess, bpmDebugRegister)
    
    1 ответ Последний ответ
    0

Powered by NodeBB | Contributors
СeLua[RU] 2024©
  • Войти

  • Нет учётной записи? Зарегистрироваться

  • Login or register to search.
  • Первое сообщение
    Последнее сообщение
0
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы