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

    Сообщения

    Последние Лучшие сообщения Спорные
    • CE рисование через дополнительный поток

      На видео показано рисование через поток и рисование без потока

      CE Native Thread

      Когда происходит рисование без потока, то окно нельзя подвинуть, не работает кнопка и даже не возможно работать с Cheat Engine

      function FilledWithPixels()
        while true do
         ::begin::
          UDF1.repaint()
          for x=1,UDF1.Canvas.Width do
              for y=1,UDF1.Canvas.Height do
                  local min = math.random(1, 0xFFFF)
                  local max = math.random(0xFFFF, 0x00FFFFFF)
                  UDF1.Canvas.SetPixel(x,y, math.random (min, max))
                  if(needReUpdate) then
                   needReUpdate = false
                   goto begin
                  end
              end
          end
          t.suspend()
        end
      end
      
      t = createNativeThreadSuspended(FilledWithPixels)
      t.name = 'New thread 1'
      needReUpdate = true
      
      UDF1 = createForm()
      UDF1.Width = 400
      UDF1.Height = 200
      btn = createButton(UDF1)
      btn.OnClick = function (sender)
        needReUpdate = true
        t.resume()
      end
      
      написал в Видео ce thread ce lua ce draw ce видео
      MasterGHM
      MasterGH
    • RE: Создать структуру программно

      Решил попробовать написать 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)
      
      написал в Программирование
      MasterGHM
      MasterGH
    • CE 6.8 Обзор нового инструмента поиска по структурам
      1. Открываем trainme Dark Byte.
      2. Проходим первый шаг (там нужно сделать One Hit Kill чит через прогресс бар, количество патронов тоже интересно поломать)
      3. Так вот на Step2 ищем адрес здоровья нашего космического корабля.
        Ставим брейкпоинт на доступ, стреляем.
        Видим, три адреса и вот теперь новые функции в контекстном меню как на скриншоте
        0745f2ad-fbcb-481d-b618-0a79d582e6cf-изображение.png
        На "(1)-(2)" - вызываем контекстное меню выделив адрес своего корабля и добавляем его в группу1. Тоже самое делаем для красных адресов кораблей противников

      На "(2)" вызываем опцию сканирования и видим "(3)"
      На (3) выбираем скан по RAX или по другим значениям. Например, когда по RAX не нашли ничего.
      Дальше видим окно и галку ставим "Only find matching groups" и сканим. Видим результат
      7e026599-701d-46c8-8e87-696877c11119-изображение.png
      Т.е. по +70 и другим смещениям можно сделать фильтр свой - чужой.

      В общем замечательный инструмент для работы со структурами с заданием уровня сканирования по оффестам

      написал в Статьи ce structure блог compare
      MasterGHM
      MasterGH
    • Создать структуру программно

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

      Пример, что будет в конце записи
      изображение.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)
      
      написал в Программирование ce structure ce lua
      MasterGHM
      MasterGH
    • Как контролировать включение и выключение скриптов в таблице

      Как контролировать включение и выключение скриптов в таблице

      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
      
      написал в Программирование ce lua условие управление
      MasterGHM
      MasterGH
    • Cheat Engine и Lua. Старт

      Где писать Lua код?

      Lua Engine окно, которое вызывается из главного окна CE.
      Lua Console окно, которое вызывается из окна отладки CE.
      Окно Autoassembler скрипта с вставки {$lua}, {$asm}

      Lua Engine окно и Autoassembler-ные скрипты могут сохраняться в файлах Cheat Engine *.CT. *.CETRAINER, *.EXE
      Lua Console для пошаговой отладки Lua кода и просмотров результатов ошибок и функции print()

      Моя первая программа

      Сначала узнаем версию для CE 6.7 и это будет первая программа
      Запускаем CE и жмем ctrl+alt+L и Lua Engine, вводим

      print(_VERSION)
      \-->> Lua 5.3
      

      Вторая программа

      showMessage('Hello World!')
      

      Следующий шаг — собрать справочные материалы и практические руководства.

      Неважно какими они будут по сложности и объему. Всегда можно будет обратиться к ним позже, когда потребуется что-то найти.

      Справочные материалы

      Если CE использует версию Lua 5.3, то нужен официальный справочник по этой версии.
      Ищем

      Lua 5.3 (https://www.lua.org/manual/5.3/)

      Cheat Engine Lua Basics (http://wiki.cheatengine.org/index.php?title=Lua_Basics )

      Category:Assembler(http://wiki.cheatengine.org/index.php?title=Category:Assembler)
      Lua Functions and Classes (http://wiki.cheatengine.org/index.php?title=Lua)
      Introduction to Lua using Cheat Engine: Beginner to Basic Script Writer! (http://dsasmblr.com/introduction-to-lua-using-cheat-engine-beginner-to-basic-script-writer/)
      Setup a Lua auto attach script (http://wiki.cheatengine.org/index.php?title=Tutorials:Lua:Setup_Auto_Attach)
      Lua Debugging (http://wiki.cheatengine.org/index.php?title=Lua_Debugging)

      Практические руководства
      Tables Tutorial (http://lua-users.org/wiki/TablesTutorial)
      Learn Lua in 15 Minutes (http://tylerneylon.com/a/learn-lua/)
      Lua за 60 минут (https://zserge.wordpress.com/2012/02/23/lua-за-60-минут/)

      Я обращаюсь к celua.txt и defines.lua. Находятся в директории Cheat Engine. В этих файлах краткое справочное руководство.

      Стоит также отметить, что Cheat Engine 6.7 написана на Lazarus. Написав, например программу по рисованию фигур, линий на форме на Lazarus или Delphi можно будет понять, как сделать также классами и функциями на CE Lua. А что нельзя сделать CE Lua, то решается внедрением и исполнения кода в саму Cheat Engine.

      Продолжение следует...

      написал в Программирование ce lua
      MasterGHM
      MasterGH
    • Большой брейкпоинт page exceptions

      Наткнувшись на тему вспомнил, что не все написал. В прошлом посте блога рассматривал бряк через DBVM. К сожалению, та версия dbvm из поста блога пропускала очень много инструкций и практически смысла нет её юзать. Например она определяла 16 инструкций, когда их было несколько тысяч, т.е. например 500 оффестов и на каждой по 10 инструкций. По DBVM надо, конечно, писать Дарк Байту, но желания нет.

      Так вот. Не только с DBVM можно ставить бряки на участок памяти. Есть еще тип брейкпоинтов page exceptions. О нем давно-давно известно и он как на ладони, но почему-то я пропустил его, когда искал оффсеты в структурах
      669b8da6-fea1-487c-9762-475e1443b7fa-изображение.png
      С ним можно работать с lua и без. Ловит огромное количество инструкций. Желательно мощное железо, т.к. игра скорее всего будет очень тормозить по 2-5 fps. Но на короткий запуск сойдет. 5 секунд и достаточно для снятия логов. На пару действий в игре тоже сойдет: выстрел или пермещение персонажа, прыжок или вообще ничего не делаем просто снимаем логи.

      1. способ поставить бряк из окна памяти. Подопытная программа "Tutorial-x86_64.exe"
        05a2e3e5-6eb5-4271-bd6f-8b7549cb949f-изображение.png
        b856f5db-cc98-43da-bfa4-a1df4e3a2df4-изображение.png
        dac22f25-9838-44f8-b695-db12e06a689c-изображение.png
        Здесь видно, что размер 720 байт

      Логи из окна инструкций CE

      1000259AE - 48 8B 00 - mov rax,[rax]
      1000259C3 - 48 8B 00 - mov rax,[rax]
      10001D70C - F7 40 50 10000000 - test [rax+50],00000010
      10001D734 - 48 8B 00 - mov rax,[rax]
      1000AAB40 - 48 83 78 70 00 - cmp qword ptr [rax+70],00
      10001D809 - F7 40 50 10000000 - test [rax+50],00000010
      10000D452 - 48 8B 0A - mov rcx,[rdx]
      10005AE70 - 83 40 68 01 - add dword ptr [rax+68],01
      1000A4CF5 - F7 40 50 10000000 - test [rax+50],00000010
      1000A4EB8 - 48 8B 00 - mov rax,[rax]
      10000DA76 - 4C 8B 32 - mov r14,[rdx]
      10005AE90 - 83 68 68 01 - sub dword ptr [rax+68],01
      100139C13 - F7 40 50 10000000 - test [rax+50],00000010
      100139C32 - 48 8B 48 60 - mov rcx,[rax+60]
      100139C46 - 48 8B 40 60 - mov rax,[rax+60]
      10009CEFB - 48 8B 00 - mov rax,[rax]
      100098850 - 8B 80 80010000 - mov eax,[rax+00000180]
      1000A4E81 - 81 88 00010000 00200000 - or [rax+00000100],00002000
      1000A4E98 - 48 8B 00 - mov rax,[rax]
      1000AD685 - F7 40 50 08000000 - test [rax+50],00000008
      10009BFB8 - 8B 40 50 - mov eax,[rax+50]
      10009816F - F7 40 50 08000000 - test [rax+50],00000008
      100098236 - 48 8B 00 - mov rax,[rax]
      10001BECE - 48 8B 00 - mov rax,[rax]
      100098419 - F7 40 50 08000000 - test [rax+50],00000008
      1000A2A28 - 48 8B 00 - mov rax,[rax]
      1000A29F4 - 48 8B 12 - mov rdx,[rdx]
      1000A4CC8 - 81 A0 00010000 FFDFFFFF - and [rax+00000100],FFFFDFFF
      10001CC58 - F7 40 50 10000000 - test [rax+50],00000010
      10000DB13 - 48 8B 00 - mov rax,[rax]
      100095C65 - 48 8B 48 60 - mov rcx,[rax+60]
      100095C75 - 48 8B 40 60 - mov rax,[rax+60]
      10001CB04 - F7 40 50 10000000 - test [rax+50],00000010
      10009BF35 - 8B 40 50 - mov eax,[rax+50]
      10009932D - 48 8B 00 - mov rax,[rax]
      10001F5C8 - F7 40 50 08000000 - test [rax+50],00000008
      10001F638 - 8B 40 50 - mov eax,[rax+50]
      100021803 - F7 40 50 08000000 - test [rax+50],00000008
      100021923 - F7 40 50 08000000 - test [rax+50],00000008
      10001ACB1 - 8B 41 50 - mov eax,[rcx+50]
      10001B850 - 48 8B 48 60 - mov rcx,[rax+60]
      10001B85C - 48 8B 40 60 - mov rax,[rax+60]
      1000A2AC0 - 48 8B 00 - mov rax,[rax]
      10013A2A3 - F7 40 50 10000000 - test [rax+50],00000010
      10013A336 - 48 8B 00 - mov rax,[rax]
      100098AC4 - 4C 8B 02 - mov r8,[rdx]
      100098AD9 - 48 8B 00 - mov rax,[rax]
      10013A35C - 48 8B 00 - mov rax,[rax]
      10008A0C1 - 48 8B 00 - mov rax,[rax]
      1000192A9 - 48 8B 12 - mov rdx,[rdx]
      1000A3B99 - 48 8B 12 - mov rdx,[rdx]
      100096636 - 8B 82 D0010000 - mov eax,[rdx+000001D0]
      10008A0ED - 48 8B 00 - mov rax,[rax]
      100097DF9 - 48 8B 00 - mov rax,[rax]
      1000A4325 - 81 B8 80010000 FF7F0000 - cmp [rax+00000180],00007FFF
      1000A6218 - F7 40 50 10000000 - test [rax+50],00000010
      1000A6240 - 48 8B 00 - mov rax,[rax]
      1000A6254 - 48 8B 00 - mov rax,[rax]
      100097727 - 48 8B 48 60 - mov rcx,[rax+60]
      100097733 - 48 8B 40 60 - mov rax,[rax+60]
      10018E4D9 - F7 40 50 10000000 - test [rax+50],00000010
      1000AA369 - F7 80 58010000 00400000 - test [rax+00000158],00004000
      1000AA394 - 48 8B 00 - mov rax,[rax]
      1000AA600 - 48 83 B8 B0020000 00 - cmp qword ptr [rax+000002B0],00
      100097E3B - 48 8B 00 - mov rax,[rax]
      1000A74A9 - 48 8B 00 - mov rax,[rax]

      1. Способ через Lua (подробнее в документации)
      debug_setBreakpoint(structure_address, sizeMemory, bptAccess, bpmException, onBreakpoint)
      

      P.S. Я написал про два способа установки брейкпоинта на множество адресов без DBVM. Вручную можно ставить такие брейкпоинты, но дальше уже кропотливый просмотр на предмет того чем это может помочь. Это может помочь определить типы данных и помочь прикинуть размер структуры, а также найти активные оффсеты. Можно на Lua автоматически определять активные offsets по базовому адресу структуры и эту структуру создать и заполнить в dessectData. Если будет время напишу скрипт.

      написал в Приёмы breakpoint фишки ce lua
      MasterGHM
      MasterGH
    • Sikulix-скрипт сравнения изображений в играх

      Вполне читерская программа Sikulix
      Помощник для нахождения отличий

      К сожалению, эту стать невозможно восстановить. Надо искать исходники.

      Игра
      Sikulix
      Документация
      Туториалы

      Sikulix умеет:

      • ждать появления или исчезновения элемента, просто ждать, периодически просматривать область в background (например игрового чата);
      • читать (и писать) текст в(/из) поля ввода, "нажимать на клавиатуру", подсвечивать области, кликать по элементам, удерживать и перетаскивать;
      • перемещаться по окнам по названию процессов;
      • сохранять скриншоты в том числе определенные области;
      • показывать много разных диалогов: ввода, тултипов, сообщений;
      • сравнивать изображения и находить отличные области (пример выше);
      • поиск элементов по маске;
      • поиск групп элементов и перебор их;
      • создание гайдов или руководств с анимациями

      Из наиболее интересных применений:

      1. в играх где необходим поиск графических элементов с действиями (кликеры, поиск отличий или поиск/подсчет элементов, маджонги и другие);
      2. нажать на найденных элементы(кнопки, чек-боксы);
      3. найти текстовое значение, перевести в число, посчитать;
      4. ожидает выхода человека из скайпа (или что-то вроде мониторинга чатов);

      Ну и так далее...

      написал в Статьи sikulix распознавание todo блог
      MasterGHM
      MasterGH
    • [The Escapists 2 + Unity + dnSpy] Спавн итемов

      Спавн итемов удалось сделать через dnSpy

      При клике на любой предмет на меню крафта он создается в инвентаре, а если там занято, то выкидывается на карту.

      Я переписал метод клика на рецепт, вот он оригинальный

      // Token: 0x060069FA RID: 27130 RVA: 0x00254874 File Offset: 0x00252A74
      	private void OnRecipeSlotClicked(int recipeSlotID)
      	{
      		if (recipeSlotID == this.m_CurrentClickedRecipeID)
      		{
      			if (!T17RewiredStandaloneInputModule.IsCurrentActiveModuleUsingController())
      			{
      				this.m_CurrentClickedRecipeID = -1;
      			}
      			return;
      		}
      		if (!this.CheckHasItemsForRecipe(recipeSlotID))
      		{
      			this.m_CurrentClickedRecipeID = -1;
      			return;
      		}
      		CraftManager.Recipe recipeByID = CraftManager.GetInstance().GetRecipeByID(recipeSlotID);
      		if (recipeByID != null && (!recipeByID.m_bHidden || recipeByID.m_bDiscovered))
      		{
      			this.FillSlots(recipeSlotID);
      			this.m_CurrentClickedRecipeID = recipeSlotID;
      			return;
      		}
      		this.m_CurrentClickedRecipeID = -1;
      	}
      

      На этот

      private void OnRecipeSlotClicked(int recipeSlotID)
      	{
      		int itemDataID = CraftManager.GetInstance().GetCurrentRecipes()[recipeSlotID].m_Product.m_ItemDataID;
      		Character character = base.CurrentGamePlayer.GetComponent();
      		ItemManager.GetInstance().AssignItemRPC(character.m_NetView.ownerId, itemDataID, new ItemManager.ItemManagerEvent(this.OnStandingAnimItemSpawn), ref character.m_StandingStillEquipID, -1);
      	}
      
      	private void OnStandingAnimItemSpawn(Item item, int eventID)
      	{
      		if (base.CurrentGamePlayer.GetComponent().m_StandingStillEquipID == eventID)
      		{
      			Player player = base.CurrentGamePlayer;
      			bool flag = false;
      			if (player.GetEquippedItem() == null)
      			{
      				flag = player.SetEquippedItem(item, true, false, RPC_CallContexts.Master);
      			}
      			if (!flag)
      			{
      				item.DropItemInLevel(player, player.transform.position);
      			}
      		}
      	}
      

      7c8381aa-0c85-466d-9743-42edabd7eb9c-изображение.png
      ac1cd6a8-5078-48ea-9f4a-3d605db0971c-изображение.png
      Для спавна заменить Assembly-CSharp.dll из архива, сделав копию предварительно
      Assembly-CSharp.rar

      написал в Статьи unity cheats dnspy csharp блог
      MasterGHM
      MasterGH
    • [dnSpy + Unity ] Пошаговая отладка

      Эта статья позволит отлаживать игры на Unity в Runtime и при этом видеть декомпилированный код.
      Это, конечно, не для всех игр на Unity. Пошаговая отладка в dnSpy позволяет ставить брейкпоинты на C# код во время работы игры, перемещаться по коду, просматривать значения переменных. Сэкономит кучу времени при поиске и отладке игрового кода,

      1. Страница загрузки dnSpy

      2. Скачиваем dnSpy и все архивы с mono.dll файлами
        Unity-debugging-4.x-win32.zip
        Unity-debugging-4.x-win64.zip
        Unity-debugging-win32.zip
        Unity-debugging-win64.zip

      3. Смотрим свойства exe файла игры и определяем по нему версию Unity. Например, "Версия продукта 5.5.0.3120186" или версия "файла 5.50.39994" может указывать на версию Unity 5.5.

      4. Определяем разрядность приложения через Process Explorer

      5. Т.к. версия Unity 5.5 и приложение 32 разрядное, то открываем Unity-debugging-win32.zip ищем там версию Unity и заменяем mono.dll в директории игры

      6. Запускаем игру и dnSpy x86 (игра 32 разрядная поэтому x86). Открываем файл "...\Managed\Assembly-CSharp.dll" Запускаем отладку нажав F5 или кнопку Play

      7. Настраиваем соединение и жмем ок
        f3bfd701-f39d-407e-88a4-7d055be62dd8-изображение.png

      8. Ставим брейкпоинты, смотрим перемененные, перемещаемся по коду, пишем свой код и так далее
        02ae6479-60bb-46ff-8a4a-29d49a3d338e-изображение.png

      9. После изменения кода, нужно перезаписать модуль предварительно сохранив его
        46ca3c49-4ed6-4dd4-8ab5-c76dd2c24810-изображение.png
        68919380-783a-4497-860a-ff2ef1809f64-изображение.png
        О других способах подключения пошаговой отладки есть на английском руководство.

      Как работать в пошаговой отладке

      Работать можно почти также как и в Cheat Engine в пошаговой отладке или в среде разработки программ.

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

      Стоит обратить внимание на такие названия как "IsPlayer, Player, Character, CharacterController, MainCharacter, Health, Inventory, Craft" и другие. Чтобы не искать вручную можно задействовать поиск сборкам. Поиск стандартного тега "Player" в виде в строки кода (в Unity выше версии 5.0) или свойства "IsPlayer" может помочь найти игрока или отличить от чужих.

      Важно представлять иерархию игровых объектов, которую мы не видим в dnSpy. Программист работая в Unity видит это окошко много лет и эту иерархию всегда представляет смотря на скрипты в dnSpy
      c4838eb6-f93c-4b24-aeda-c733de7ffb51-изображение.png
      Скрипты наследники от MonoBehavior могут находиться на игровом объекте и могут работать как с ним так и с другими объектами. Получается такая штука, что игровой объект всегда имеет Transform компонент с полями позиций, углами и scale. Классы Transform и GameObject самые основные. Методами этих классов можно разместить объект в мире, создать или удалить его. В идеале удалив объект со сцены не должно быть никаких ошибок связанных с пустыми ссылками, потерей объекта. Также и клонировав объект, тоже не должно быть ошибок. Но не всегда так просто отспавнить игровой объект. Если это сделать методами UnityEngine, то другие классы ничего не будут знать о появлении игрового объекта. Нужно ставить брейкпоинт в функции Start или Awake в классе и трейсить по Shift+11 чтобы выйти на функцию разработчиков спавна этого GameObject. Функции Start или Awake (в классе наследника от MonoBehavior) срабатывают один раз при включении скрипта и инициализации. По ним можно выйти на строку кода, которая создает объекты в мире.

      Отдельно стоит сказать про количество скриптов. Практически в любой игре, которая мне попадалась в dnSpy много скриптов или очень много. Иногда и не будет понятных названий у типов (из-за обфускации). В любом случае при пошаговой отладке можно найти требующиеся участки кода для создания чита и использовать их по другой логике.

      Основные приемы

      В Update можно обновлять параметры только своего игрока. Например, в Character классе сделать сравнения в Update по IsPlayer свойству (если оно там есть) и у тебя за каждый кадр рендеринга будет максимум характеристик.

      В Update с классом Input можно считывать хоткеи.

      В Start и Awake можно подгружать свои ассеты с внутриигровым user interface. Код скриптов перед загрузкой ассетов должен быть внедрен через dnSpy

      Иерархию игровых объектов и инспектор, если очень нужно, то можно отрисовать в user interface. Обычно не требуется. (поищите по форуму в игрострое)

      В заключении

      Пока нет времени делать трейнер или таблицу на CE для включения опций в играх Unity. Для меня пока подходит способ через перезапись модуля в dnSpy вручную.

      Вместо трейнера можно сделать программу патчер, который будет проверять версию игры и перезаписывать модуль с возможностью вернуть оригинальный модуль

      написал в Статьи unity dnspy decompile debug блог
      MasterGHM
      MasterGH
    • RE: Настройка частного DNS

      Ого 😃 Ну, спасибо

      написал в Linux
      MasterGHM
      MasterGH
    • RE: Защита Трейнера

      Пользовательские метки должны здесь появится.

      изображение.png
      изображение.png

      Если их там нет, значит они не зарегистрировались. Чтобы они зарегистрировались нужно использовать reinitializeSymbolhandler(true) до autoassemble(...)

      написал в Вопросы
      MasterGHM
      MasterGH
    • Настройка частного DNS

      Статья "Настройка частного DNS"
      ссылка en
      перевод ru

      написал в Linux linux dns server ubuntu
      MasterGHM
      MasterGH
    • CE Script Editor [Notepad+]

      Расширение для Notepad+
      Там все файлы и ссылки: перейти
      Пару картинок запосчу, чтобы иметь представление что это

      Описание
      Описание

      Не хватает изменения размеров картинок.
      Не хватает спойлеров (добавил в todo)
      Не хватает цвета для текста

      написал в Плагин-строй todo ce plugin notepad++
      MasterGHM
      MasterGH
    • Собираем ссылки на разные источники

      В этой теме собираем все, что понравилось и плюс небольшой комментарий. Можно по CE, можно не по CE. Как угодно. Потом сгруппируем, как больше накопится

      1. Базовые основы CE Auto Assembler Basics
        Auto Assembler Basics

      2. Вся справка по CE

        Cheat Engine
      3. Статья из блога по шаблонам CE (сложно, для понимания надо хорошо знать CE Lua)

        Ну, а сам блог можно полистать там. Там есть например настройка DNS
        И сам движок прикольный блога с тегами
        c0a3a943-0e68-4eaa-90f3-bf3fc8c98a15-изображение.png Надо будет такой же поставить (записил в todo). Шаблоны на CE Lua того же автора (альтернатива AAMaker)

      4. Сам форум CE (там куча всего). Наиболее интересный для меня раздел по CE Lua плагинам.

      5. Отличный форум "FearLess Cheat Engine"
        Лучшие авторы. Можно найти их сообщения. Перейти

      6. Книга программиста из Electronic Arts. Создание игр на C++. Офиц. версия

      7. Семантическое Версионирование 2.0.0. Всегда хотел узнать что означают точки в названии версии? Тогда сюда

      Продолжение следует...

      написал в Статьи todo источники
      MasterGHM
      MasterGH
    • RE: Защита Трейнера

      Мой вариант был не рабочий. Я толком не проверил, потому что мой бинарник тоториала не подходил.

      Рабочий вариант. Если хочешь, то попробуй запустить мой вариант (если нужен, то мой exe туториала там же). А потом из моего примера сделать твой, который заработает на двух бинарниках.

      написал в Вопросы
      MasterGHM
      MasterGH
    • RE: Рубрика "Lua код сегодня" №5 (активирующий скрипт)

      Update:
      Если скрипт не запускается, то вызывать reinitializeSymbolhandler(true)
      Пример здесь

      написал в Обучающие примеры
      MasterGHM
      MasterGH
    • Запустить активирющий скрипт CE 7.5

      Tutorial-i386.CT

      Бинарник тутораала(шаг1):Tutorial-i386.zip

      Смысл в следующем. Нужно активирующий скрипт перенести в Lua. Как оказалось для корректности нужно использовать reinitializeSymbolhandler(true)

      aa_script = [[
      { Game   : Tutorial-i386.exe
        Version:
        Date   : 2023-04-08
        Author : 79777
      
        This script does blah blah blah
      }
      
      [ENABLE]
      aobscanmodule(INJECT_tut1,Tutorial-i386.exe,81 BB B0 04 00 00 E8 03 00 00)
      
      alloc(newmem,$1000)
      alloc(newmem2,$1000)
      label(code)
      label(return)
      label(pointer_ebx)
      registersymbol(pointer_ebx)
      
      newmem2:
      pointer_ebx:
       dd 00
      
      newmem:
        mov [pointer_ebx],ebx
      code:
        cmp [ebx+000004B0],000003E8
        jmp return
      
      INJECT_tut1:
        jmp newmem
        nop 5
      return:
      registersymbol(INJECT_tut1)
      
      [DISABLE]
      //code from here till the end of the code will be used to disable the cheat
      INJECT_tut1:
        db 81 BB B0 04 00 00 E8 03 00 00
      
      unregistersymbol(INJECT_tut1)
      dealloc(newmem)
      dealloc(newmem2)
      
      {
      // ORIGINAL CODE - INJECTION POINT: Tutorial-i386.exe+25DD3
      
      Tutorial-i386.exe+25DC1: 85 C0                          - test eax,eax
      Tutorial-i386.exe+25DC3: 74 05                          - je Tutorial-i386.exe+25DCA
      Tutorial-i386.exe+25DC5: E8 B6 7D FE FF                 - call Tutorial-i386.exe+DB80
      Tutorial-i386.exe+25DCA: 5E                             - pop esi
      Tutorial-i386.exe+25DCB: 5B                             - pop ebx
      Tutorial-i386.exe+25DCC: 89 EC                          - mov esp,ebp
      Tutorial-i386.exe+25DCE: 5D                             - pop ebp
      Tutorial-i386.exe+25DCF: C3                             - ret
      Tutorial-i386.exe+25DD0: 53                             - push ebx
      Tutorial-i386.exe+25DD1: 89 C3                          - mov ebx,eax
      // ---------- INJECTING HERE ----------
      Tutorial-i386.exe+25DD3: 81 BB B0 04 00 00 E8 03 00 00  - cmp [ebx+000004B0],000003E8
      // ---------- DONE INJECTING  ----------
      Tutorial-i386.exe+25DDD: 75 2D                          - jne Tutorial-i386.exe+25E0C
      Tutorial-i386.exe+25DDF: 8B 83 9C 04 00 00              - mov eax,[ebx+0000049C]
      Tutorial-i386.exe+25DE5: B2 01                          - mov dl,01
      Tutorial-i386.exe+25DE7: 8B 8B 9C 04 00 00              - mov ecx,[ebx+0000049C]
      Tutorial-i386.exe+25DED: 8B 09                          - mov ecx,[ecx]
      Tutorial-i386.exe+25DEF: FF 91 20 02 00 00              - call dword ptr [ecx+00000220]
      Tutorial-i386.exe+25DF5: 8B 83 A8 04 00 00              - mov eax,[ebx+000004A8]
      Tutorial-i386.exe+25DFB: 30 D2                          - xor dl,dl
      Tutorial-i386.exe+25DFD: 8B 8B A8 04 00 00              - mov ecx,[ebx+000004A8]
      Tutorial-i386.exe+25E03: 8B 09                          - mov ecx,[ecx]
      }
      ]]
      
      
      function onOpenProcess()
        reinitializeSymbolhandler(true)
        local checkOk, errMsg = autoAssembleCheck(aa_script, true, false)
        if not checkOk then
           print('Ошибка в активирующем скрипте')
           print(errMsg)
           return
        end
      
        is_enabled, disabled_info = autoAssemble(aa_script)
      
        if not is_enabled then
           print('Ошибка. Не запущен активирующий скрипт')
        end
      end
      
      getAutoAttachList().add("Tutorial-i386.exe")
      
      написал в Управление ce aa active rec ce lua важно
      MasterGHM
      MasterGH
    • Заполнение разделов старыми постами

      Перенос старых тем, постов, блогов, видео по разделам

      написал в Новости todo
      MasterGHM
      MasterGH
    • RE: Ваши группы пользователей

      В ступать и выходить из групп можно самому без админа? (Проверить)

      написал в Новости
      MasterGHM
      MasterGH
    • 1 / 1