Перейти к содержанию
  • записи
    104
  • комментариев
    125
  • просмотров
    15 630

Cheat Engine 6.7 и Lua. Часть 3


MasterGH

1 829 просмотров

Наконец-то дошли руки до третий части.

 

Речь пойдет о создании структур программно. Пример, что будет в конце записи

 

Screenshot_9.png

 

Сразу к делу. Нужен поинтер и процесс.

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

 

Подключаемся к процессу идем на 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()

 

 

Результат

Screenshot_9.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)

 

 

upd: спрятал код под спойлеры

  • Понравилось 2
  • Плюс 1

0 Комментариев


Рекомендуемые комментарии

Комментариев нет

Пожалуйста, войдите, чтобы комментировать

Вы сможете оставить комментарий после входа в



Войти
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.