Перейти к содержанию

MasterGH

Ветераны
  • Постов

    2 999
  • Зарегистрирован

  • Победитель дней

    129

Записи блога, опубликованные MasterGH

  1. MasterGH
    Пример, который показывает как снять стек вызовов функций
    function A0() -- Здесь можно удалить ":gsub('\n','\r\n')", но тогда в консоли текст будет в одну строку print(debug.traceback():gsub('\n','\r\n')) end function A1() A0() end function A2() A1() end function A3() for i=1,3 do A2() end end A3()  
    Можно поставить пошаговую отладку в консоли Lua (как на скриншоте) и  пройти по шагам
  2. MasterGH
    Я обратил внимание на следующие поведения записи и чтения
    1. Срабатывают только инструкции чтения до изменения параметра, адрес рабочий
    С адресом работают инструкции на чтение, но если в друг в этом адресе что-то поменять (например в CE), тот тут же выскочат инструкции на запись. Нельзя однозначно утверждать, что адрес является настроечным параметром, но и нельзя утверждать, что это не рабочий адрес. Какая-то инструкция может жестко менять значение, а может быть будет "стараться" изменить значение адреса в меньшую или большую сторону, но адрес при этом будет рабочим.
    2. Срабатывают инструкции записи и чтения, адрес не рабочий
    Запись и чтение влияет только на часть игры, а не на все или вообще не влияет, а перезаписывается постоянно. Например, на визуальное отображение полоски со здоровьем. Получается, что адрес не рабочий, а у него есть как и в первом пункте инструкции и на запись, и на чтение.
    3. Один раз срабатывает инструкция записи и потом всегда на чтение
    Если попался такой адрес в структуре, то он точно является "настроечным" и рабочим адресом. Например, это какой-то коэффициент, который добавляет, умножает, отнимает... в общем что-то меняет. Что с ним не делай, это адрес будут только "читать". Также это может быть булевой параметр "1 "или "0" и по нему может что-то резко меняться в игре.
     
    Окей. Вспоминается окно с кучей инструкций и счетчиков уникальных адресов (не более 8-ми логируется)

    Постреляв патроны  с адресом патронов (в СТАКЛЕРЕ Зов Припяти) сработали инструкции как на запись, так и на чтение.
     
    Первая инструкция читает очень часто, вторая редко. В круглых скобках обозначаются количество проскакивающих адресов.
    Если был выстрел и значение поменялось, то вылезли инструкции записи (все после первых двух).
     
    Код читает в цикле адрес...и если, что поменялось, то запишет в него потом.
    Это похоже на пункт1, который обсуждали выше, но этот адрес патронов не тот, который нужен. С виду рабочий, но патроны потом не стреляют. Патроны это структуры в памяти, а адрес их как  счетчик структур
     
    Как можно делать
     
    Создаем две группы (скрин ниже). Первая текущая и не замороженная. Вторая с двумя замороженными состояниями, когда стоим и ничего не делаем.
    Делаем несколько выстрелов.
    Цвет по +AC нас интересует больше всего, он соответствует логике состояний (стреляю и (не стреляю и не стреляю))

     
    Выделяем и перемещаем адреса этого цвета и морозим в таблице.
     

    Первый праметр это прочность, второй не знаю. Третий счетик патронов. 3 и 5 адреса связанные, если правильно помню, с объектами патронов
    В Сталкере это не даст беск. патрнов, но в других играх может иметь смысл как прием сравнения структур и групп.
     
    p.s. По Сталкеру Зов Припяти, к сожалению, у меня не было времени взломать патроны или может быть я не умею, не знаю. Какие-то патроны в сталкерах ломал, но не помню как.
  3. MasterGH
    Немного комментариев к этой версии.
     
    1. Исправлены смещения
    2. Добавлены также инструкции на запись
     
    На скриноте ниже пример сравнения текущей структуры с координатами в СТАЛКЕРЕ Зов Припяти с копией структуры.
     
  4. MasterGH
    Проведено огромное количество опытов над структурами. Много переделок.
    Очень кратко напишу, что поменялось.
     
    1. Название структуры состоит из адреса, количества адресов в ней и  времени в миллисекундах на один байт в структуре.
    Подчеркнуто красным

     
    2. Смещения отбираются только те, на которых за X времени не было обнаружено ни одной инструкции на запись. Чем больше та самая чувствительность,  тем точнее результат
    3. В именах структур теперь ценная информация. Это смещение, регистр и тип
     
    На скриншоте ниже можно посмотреть пункты 2 и 3.
    Также на этом скриншоте я заморозил по соседству адрес (поставил Lock) и пару раз пострелял в игре Сталкере Зов Припяти
     

     
    Выводы, которые я сделал за очень и очень скромное время пользования. За минут 15 и на паре структур оружия в двух разных играх L4D2 и Сталкер Зов Припяти
    1. Если править 4-х байтовые значения, то легко можно нарваться на вылет игры. Но подключившись снова, можно продолжить.
    2. Правки значений с типом в 1 байт могут заблокировать оружие (в двух играх) или же устроить скорострельность на полную катушку в L4D2.
    3. Правки значений с типом float. Можно легко нарваться на вылет в игре, если например поставить нолик. Деление на ноль или какая-то иная причина. Лучше ставить чуть больше нуля, можно положительные или отрицательные значения
    4. Частенько бывают адреса в структуре, на которых включаются инструкции записи только после изменения значения. Тут я пока ничего не смог сделать, просто удалить их из структуры как лишние.
    5. Для сканера используется 1 аппаратный брейкпоинт, остальные три штуки еще не используются, т.к. сложно их прикрутить. Если использовать все 4 аппаратных бряка, то скорость сканера была бы в 4 раза быстрее. Сейчас на 2К байт по 10 мс, у меня уходит где-то 150 секунд. Если я ставил 20мс, то находилось на 10 смещений больше или какие-то другие смещения пропадали.
     
    Код будущего плагина все еще находится на стадии тестирования. Поэтому пока плагин не выкладываю.
     
    upd1:  инструкции cmp, add, sub, xor, and, not, test, mulss, fsub, fmul, dec, inc, mul; теперь выводятся в имя элемента структуры.
    На скриншоте случайно вышел на координаты UI таймера. Сделал три скана трех структур в новых окнах

     
     
    upd2: перемещение структуры



     
    Итог перемещения двух структур в первую

     
     
  5. MasterGH
    Охота на структуры и удивительное путешествие в мир структур в L4D2
     
    1. Игру L4D2 в оконный режим
    2. Установка плагина (позже)
    3. Установка VEH отладчика, иначе вылеты
    4. Первая миссия. Ищем адрес патронов. Бряк на адрес. Нашли инструкцию

    Красным показано, что я не всю структуру проанализирую позже. Долго было ждать. Структура больше 5К байт...
     
    5. Делаем сигнатуру любой инструкции при работе  с патронами на всякий случай, если игра вылетит.
    server.dll,83 BE 14 14 00 00 00 7F 4D 6. Переходим в код и ищем проскакивающие адреса на инструкции. Там один адрес нашего  пистолета. Клик на него и переносим адрес начала будущей структуры в окно Dissect Window.  Можно не создавать структуру (отказываемся). Кликаем "Scanner" (он будет на всех окнах dissrct data)
     

     
    7. Далее побежало сканирование.

     
    В игре можно что-то делать, можно ничего не делать. Долго ждать..
     
    Меняю опции. Чувствительность как была так и осталась минимальная (это время ожидания прерывания на адресе умноженное на коэфициент чувсвительности и на 100 мс).  Размер структуры меняю, до 1100

     
    Наконец ~30 секунд дождался без вылетов (иногда бывают,  возможно из-за VEH). Появился результат

     
    Самые интересны это байтовые и float значения. и инструкции чтения. Их определит можно пока только по логам...
     
    Меняю первый байт на 1 и пистолет стал очень быстро стрелять.

     
    Ради чего это все и делалось, чтобы похожие адреса искать...
     
    Если сравнить дефолтную расструктуризацию, она слева

     
     
    Логи (для меня и для желающих) по определению типа по опкодам
     
    Плагин выложу позже. Надо еще доработать и потестить.
     
    Вот к примеру float распознал как Pointer и там где fst тоже по +42C тоже фигня. Это ошибки. Это быстро поправить, но могут быть еще ошибки.

     
    Не менее интересны еще вложенные структурки, которые удается раскрыть (не все). Вот одна из них и усеяна параметрами, которые можно покрутить

     
    Вложенные структуры пока отдельно можно создавать в окнах, чистить сканером, потом подставлять их в основную структуру по имени. В общем пока рано об этом писать.
     
    Больше всего меня волнует польза, т.е. что можно с этим сделать. Пока только сразу вышел на скорострельность. Еще шесть параметров покрутил байтовых, ничего не дало. Надо еще попробовать выводить только смещения, которые работают на инструкцияъ чтения, а не "чтении и записи". Запись скорее всего не нужна. Значения просто активно перезаписываются  в структуре. А вот оставлять смещения,  с которыми работает только "чтение" скорее всего даст куда больше вероятности найти параметр настройки.
  6. MasterGH
    Конечно не секрет, что типы данных не правильно определяются. Вот пример для 50-ти адресов
     
    Слева как определил данные CE. Справа как определил их я по логу ниже

    Понравились данные с размером в 1 байт, привлекают в нимание. Как только я переключил на ноль или 1, то персонаж перестал двигаться и не реагировал на движение.
     
    Лог инструкций
     
    Пытаюсь по логам определить алгоритм для Lua, чтобы скрипт сам ставил тип и смещение. Конечно есть сюрпризы, когда регистр перезаписывает сам себя и еще куча опкодов. Чтобы получить такой лог мож попробовать этот скрипт. Он черновой
     
     
  7. MasterGH
    Решил попробовать написать CE Lua  скрипт, который прочесывает структуру и в Dissect data/structures окне создавал бы структуру только со смещениями, с которыми код работает, т.е. читает или пишет.
     
    Например, мой персонаж прогуливается по городу, а каждые 200 мс ставится брейкпоинт на смещение +1 до гипотетической N границы структуры (например до 4096).
     
    Я не успел сделать определение типа, но смещения внутри структуры получить я успел.
     
    Итак, находим начало структуры любой. Запускаем Lua скрипт и просто что-то делаем в игре. Потом вылазит текст с дизассемблированными инструкциями и смещениями. Уже по этим логам можно определить вручную
    1) к каким смещением было обращение (адреса по ним мы и будем менять или сравнивать структуры между собой позже)
    2) по виду инструкции и соседнему смещению уже примерно можно определить тип данных и их размер
     

     
    Осталось сделать определение типа, а это не так уж долго сделать  и осталось взять код из предыдущих записей в блоге формирования структуры в окне dessect data. Так мы получим структуру только с активными смещениями, (а зачем нам пассивные?) и определим в них тип, я надеюсь определим правильно
     
    Пример кода, который я использовал
     
  8. MasterGH
    1. Персонаж падает с большой высоты и разбивается
     
    Ищем адрес скорости прыжка прыгая под speedhack. Находим эту скорость. Ставим бряк на доступ. Прыгаем.
    Инструкции на чтение добавляем в список адресов и там начинаем нопить
    - Либо по одной
    - Либо рискнем по половине от половины
    - Либо рискнем и все сразу занопим
     
    Если повезет, а должно повезти, то инструкция не прочитает то значение скорости, которое уложило бы персонажа на землю и можно будет прыгать на огромную высоту.
     
    2. Как делать супер прыжок
    Ищем под speedhack скорость float (назовем её velocityZ, Z - вертикальная ось) по вертикальной оси прыгая персонажем. Когда прыгаем. то скорость в один момент увеличивается. Затем, скорость постоянно уменьшается от положительного до отрицательного значения.  Когда на земле, то скорость быстро записывается и равна нулю.
    Дальше смотрим что это рабочий адрес. Прыгаем и замораживаем значение. Если адрес рабочий, то персонаж зависает в воздухе или движется.
    Дальше ставим бряк на запись на этот адрес и снимаем speedhack
    Прыгнули и увидели инструкции. Например одна из них будет
    movss [rdi+0000010C],xmm0 и работает каждый раз при прыжке по одному разу за прыжок (прыгнули — сработала, прыгнули — сработала).
    Вот в неё и легко сделать инъекцию с рядом стоящими адресами с умножением на scale величину. Все и персонаж будет с суперпрыжком. Чтобы он не разбивался при прыжке смотрим пункт1
     
    Еще один вариант — не писать инъекцию кода, а искать адрес силы прыжка в структуре.
    Это можно сделать меняя значения в структуре где-то рядом с [rdi+0000010C] и смотреть что происходит в игре. Можно найти, а можно и не найти, и возможно этот процесс будет долгий.
    Еще можно в пошаговой отладке пройтись, посмотреть стек, протресить и попробовать найти адрес в структуре (при чем структура не обязательно будет с адресом в rdi) без рандомного поиска в структуре. Но у последнего есть свои плюсы, можно найти разные параметры движения игрока и увидеть изменения в игре.
     
    3. Менять данные в структурах или менять код?
     
    В примере выше пришлось создать два новых поля
    scaleXY: dd (float)4 scaleZ: dd (float)4 И умножать их на скорости X,Y,Z персонажа.
     
    С одной стороны больше кода писать и добавлять новые поля, а с другой стороны выделить время и найти подход к поиску значения стартовой скорости в структуре. Можно в структуре ничего не искать, а написать скрипт выше и это может быть быстрее чем искать в структуре. С другой стороны если в структуре рандомно ставить параметры в течении времени X на 4К байт, то можно найти: адрес скорости, адрес гравитации, адрес чувствительности и много чего еще.
     
    И еще одно ограничение. Расструктуризация не всегда правильная. Упорно вместо float может видеть 4 байта.  Это в лучшем случае, в худшем разные смешения смержены и выводятся разные типы данных.
    В общем исследование игровой структуры эта тема интересная. Можно сказать это поиск свойств, по которым будет меняется поведения персонажа в игре. Структуру желательно обследовать какой оффест, что делает и какого он типа (через брейкпоинт). Это всего 4К байт проанализировать. Каждое смещение подписать и сохранить. Сделав это вы скажите себе я исследовал всю структуру и знаю, что делает смещение.
     
    Lua может помочь автоматизировать анализ структур и пока я думаю об этом. Данные структур могут сильно повлиять на поведение персонажа,  на прохождение потоком отладочных инструкций игры по разным условиям — выполнять и не выполнять ответвления кода с разными условиям. В общем есть над чем подумать.
     
    Всегда было приоритетным менять код, но теперь стал задумываться о том чтобы больше смотреть в сторону правки данных структур. Фактически код мы не правим, а меняем данные и код работает уже с другими данными.
  9. MasterGH
    Наконец-то дошли руки до третий части.
     
    Речь пойдет о создании структур программно. Пример, что будет в конце записи
     

     
    Сразу к делу. Нужен поинтер и процесс.
    Запустим туториал из Cheat Engine из меню Health->Cheat Engine Tutorial.
    Прохождение туториала подробно описано здесь
     
     
    Подключаемся к процессу идем на 8-мой шаг. В руководстве есть поинтер
    [[[["Tutorial-i386.exe"+XXXXXX]+C]+14]+0]+18  
    Вместо XXXXXX может быть любое смещение. Поэтому надо бы поискать
     
    Нашил адрес.
    Поставили бряк.
    Нашли esi
    Поставили бряк
     
    Вышли сюда
    Поинтер получили, дальше пойдет Lua.
     
    Открываем Lua консоль и проверяем поинтер
    Выведем адрес и его значение
    Окей. Поинтер верный.
     
    Другой вариант читать значение поинтера примерно такой
    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"
    Если выполнить скрипт выше, то мы построим структуру одного уровня.
     
    Построим теперь структуру двух уровней  "[005FD660]+C". Второй уровень нужно развернуть

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

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

      Полный скрипт
     
    Результат

     
     Ну и на закуску.
     
    Допустим мы знаем что по адресу 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 Ну и вот два примера
     
    upd: спрятал код под спойлеры
  10. MasterGH
    Как контролировать включение и выключение скриптов в таблице
     
    AA или "Autoassembler code" код похожий на язык программирования ассемблера.

    Обычный АА-скрипт состоит из двух директив и добавляется в таблицу CE как запись
    // Код срабатывающий как при активации, так и при деактивации [ENABLE] // Код активации [DISABLE] // Код деактивации Чтобы код активировался, нужно включить галку напротив записи в таблице и наоборот выключить.
    Есть такие директивы как {$lua} и {$asm}.
    Под {$lua} пишут Lua скрипт, под {$asm} пишут АА-скрипт.
    Мы можем проверить Lua скриптом любое условие и разрешить включать галку или выключать галку. Например, через "syntaxcheck" — проверку синтаксиса или другое условие .
    Если проверка не прошла, то не получится галку включить и не получится выключить, если что-то пойдет не так.
     
      В Lua строка из двух минусов "--", обозначает комментарий.

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

       Следующий вариант проверяет открыт ли процесс. Если нет, то покажет сообщение.
     
    Как узнать, что процесс был закрыт после открытия

      process - зарезервированное переменная, показывает что процесс открыт

    В комментариях можно увидеть при каких условиях блокируются включение галки
     
     
  11. MasterGH
    Где писать 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, то нужен официальный справочник по этой версии.

    Ищем

    Я  обращаюсь к celua.txt и defines.lua. Находятся в директории Cheat Engine. В этих файлах краткое справочное руководство.
     
    Стоит также отметить, что Cheat Engine 6.7 написана на Lazarus. Написав, например программу по рисованию фигур, линий на форме на Lazarus или Delphi можно  будет понять, как сделать также классами и функциями на CE Lua. А что нельзя сделать CE Lua, то решается внедрением и исполнения кода в саму Cheat Engine.
     
    Продолжение следует...
     
    upd: добавил ссылку Category:Assembler
  12. MasterGH
    Есть инструкции, которые добавляют мусора больше чем другие.
     
    Показываем объем памяти мусора
    print(string.format('Lua memory usage %.1f MiB',collectgarbage('count')/1024)) Ниже код того как попробовать узнать сколько мусора добавил код при парсинге ассемблерной строки двумя способами
     
    Пример результатов могут отличаться. Фиг его знает почему. Возможно работает сборщик мусора в разные моменты времени
    Lua memory usage 1.8 MiB Lua memory usage 1.8 MiB Lua memory usage 1.8 MiB 1.49 Lua memory usage 1.8 MiB Lua memory usage 2.3 MiB Lua memory usage 2.3 MiB 1.47 Lua memory usage 2.3 MiB Lua memory usage 2.8 MiB Lua memory usage 2.8 MiB 1.49  
  13. MasterGH
    Появилась такая опция асинхронного выполнения скриптов

     
    Если эту опцию поставить на скрипты, то появляются вот такие часики

     
    АА-шные скрипты могут искать в этот момент сигнатуру.
    Lua скрипты потестить было интересно, узнать действительно ли асинхронно выполняется. Например, один скрипт выполняет счет, второй выполняет счет. По выполнении выводится результат.
     
     
    Во время выполнения включаем первую галку. Тут CE подвисает. Затем успеваем нажать на вторую галку. Видим как две иконки часов работают.

     
    После выполнения

     
    Если продублировать 4 скрипта, то видим, что нельзя запустить асинхронно более двух скриптов

     
    Возможно, я Lua код где-то не правильно написал. Вот такой вариант еще делал
     
    Asynchronous testing.CT
  14. MasterGH
    Я задался вопросом, что такое pointermap. Вообще о нем не слышал и речь пойдет о нем. Я узнал о нём и прикинул, что возможно круто, а возможно и не круто иметь готовую цепочку указателей перед тем, как что-то делать в отладке. Цепочки можно раскрыть в окне структур и прикинуть, что там в них и "около" каких адресов будет происходить отладка. Во время отладки можно смотреть на окна структур. Может быть, а может быть и нет что-то интересное связать в отладке и с данными об указателях...
     
    На видео сравниваются два способа поиска указателей в Cheat Engine 6.7: классический и используя pointermap. Судя по видео последний  эффективнее по времени,  действиям и результатам поиска. Конкретно для этого случая с помощью pointermap сканирования нашлось несколько цепочек указателей.
     
    Можно предположить, что на других играх стоит попробовать этот способ. Способ с pointermap начинается со времени 9:21.
     
     
  15. MasterGH
    Пошаговая отладка в 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 или кноgку Play
    7. Настраиваем соединение и жмем ок

    8. Ставим брейкпоинты, смотрим перемененные, перемещаемся по коду, пишем свой код и так далее
    9. После изменения кода, нужно перезаписать модуль предварительно сохранив его
     
    О других способах подключения пошаговой отладки есть на английском руководство.
    ----------------------
     
    Как работать в пошаговой отладке
     
    Работать можно почти также как и в Cheat Engine в пошаговой отладке или в среде разработки программ.
    Начать стоит с обзора названия пространств имен, названия классов, методов и полей, Названия могут подсказать логическую связь с читом, который хотим сделать.
    Стоит обратить внимание на такие названия как "IsPlayer, Player, Character, CharacterController, MainCharacter, Health, Inventory, Craft" и другие. Чтобы не искать вручную можно задействовать поиск сборкам. Поиск стандартного тега "Player" в виде в строки кода (в Unity выше версии 5.0) или свойства "IsPlayer" может помочь найти игрока или отличить от чужих.
     
    Важно представлять иерархию игровых объектов, которую мы не видим в dnSpy. Программист работая в Unity видит это окошко много лет и эту иерархию всегда представляет смотря на скрипты в dnSpy

    Скрипты наследники от 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 вручную.
    Вместо трейнера можно сделать программу патчер, который будет проверять версию игры и перезаписывать модуль с возможностью вернуть оригинальный модуль
  16. MasterGH
    Спавн итемов удалось сделать через dnSpy.
    При клике на любой предмет на меню крафта он создается в инвентаре, а если там занято, то выкидывается на карту.
     
    Я переписал метод клика на рецепт, вот он оригинальный
     
    На этот
     
     
     
    Для спавна заменить Assembly-CSharp.dll из архива, сделав копию предварительно
    Assembly-CSharp.rar
  17. MasterGH
    ИМХО отказываться от CE Lua скриптов из-за утечек памяти не стоит.
    Можно чистить память следующим образом
    function startCollectgarbageProcess(interval, showStatus) local timer1 = createTimer(true) timer1.Interval = interval timer1.onTimer = function () if (showStatus) then print(string.format('Lua memory usage %.1f MiB',collectgarbage('count')/1024)) end collectgarbage("restart") collectgarbage("collect") if (showStatus) then print(string.format('Lua memory usage %.1f MiB',collectgarbage('count')/1024)) end end end -- Собирать каждую 1 минуту и показать результат startCollectgarbageProcess(60000, true)  
  18. MasterGH
    Игра с рандомом. Есть счет.
    Запускается через таблицу в аттаче.
     
    Здесь мог быть AI на Lua, возвращающий номер клетки от 1 до 9.
    function InputAI() -- рандом return math.random (1, 9) end Извиняюсь, лучше рандома пока не могу предложить.
     
     
    Крестики и нолики.CT
  19. MasterGH
    Поиск по модулям
     

     
    Исходник
     
    Поместить ModuleListRegioScan.lua в autorun.
     
    Что интересно, Дарк Байт решил написать на Lua. Эта функция жестко в CE не впиливается. Можно выбирать, хочу это расширение поставить или нет. Посмотрел, если понравится, то оставил. Cheat Engine перекомплировать не нужно и не нужно в нем делать опции скрывать или показывать функционал.
     
    Источник
  20. MasterGH
    Источник
     
    Как вступление. Мне нравится Lua, потому что в нем можно писать код в виде строковых данных (и Lua строки, и ассемблерные строки), а затем выполнять эти строки как код. В теории код может по фидбеку делать другой код в автоматическом режиме. Это на мой взгляд неисчерпаемые потенциальные возможности AI ограничивающиеся железом.
     
    В CE 6.7 функция autoAssemble вызываемая в Lua скриптах позволяет включать и теперь выключать скрипт со "своим" dealoc-ом.
     
    Пример.
     
    Функция активации и деактивации:
     
    enableInfiniteHealthCheat()
    disableInfiniteHealthCheat()
     
    // По стилю функции на Lua пишут с буквы в нижнем регистре. Вместо табуляции два пробела. Данные с большой буквы.
     
     
  21. MasterGH
    Напишем функцию, которая в 3.2 раз быстрее кода ниже
    splitDisassembledString(disassemble(address))  
    Сравнивая скорости получаем оптимизацию в ~3.20 раза быстрее.
     
    Пример использования
    function GetDebugString2(address) local clearString = string.gsub(disassemble(address), '%s','') return string.match(clearString, '^(.-)%-(.-)%-(.-)$') end local address, bytes, opcode = GetDebugString2(0x0045464A) print(address) print(bytes) print(opcode) gsub очищает пробелы, а выражение '^(.-)%-(.-)%-(.-)$' позволит захватить данные между тире в строке.
     
    Может пригодится, когда трейсим своим Lua кодом.
    Если заинтересовали регулярки: ссылка
  22. MasterGH
    Инфа по совместной работе с гитом. Может быть пригодится кому, а может и нет. Такую систему я использую на работе недавно.
     
    Можно совместно работать над одним большим проектом через git-flow. Возможно, кто-то из форумчан тоже использует git flow на работе.
     
     
    Кратко. Модель контроля версии построена на 4 ветках
     
    master - релизы
    develop - разработка
    feature - фичи
    hotfix - исравления
     
    С develop начинается разработка через копирования в ветку feature.
    Над фичей идет работа, а после завершения feature мержится с develop и feature сразу удаляется.
    После запланированных изменений develop мержится с master уходя в релиз.
    Если возникли баги, то от master создается ветвь на hotfix . После фиксов hotfix мержится с master.
     
    Доступ к мастер ветки может иметь один человек или его доверенные лица. Ветка Develop открыта для разработчиков. Это значит, что множество разработчиков колдуют в Develop ветке, а мержит изменения с master уже главный разработчик или несколько главных разработчиков.
     
    В мастере создаются теги с обозначением версии.
     
    Шпаргалка по git-flow: ссылка
    Семантическое версионирование : ссылка
  23. MasterGH
    Нажали checkbox — заполнились данные по базовому адресу

     
    Отжали checkbox — удалились данные

     
     
    Если проще руками забить и поставить опцию раскрытия, то можно и без скрипта.
  24. MasterGH
    Был вопрос на форуме о том, как узнать, а куда смотрит игрок и как нарисовать линию в экранных координатах.
    Я не нарисую отрезки в окне игры в экранных координатах, но могу отобразить точки одного отрезка для одного глаза 2д-панельками в экранных координатах (хотя визуально, у Unity экранные координаты связаны с 3д координатами по масштабу пикселя на метр на сцене). Для наглядности все же в окнах сцены будут отрезки в 3д-координатах.
     

     
     
     
    Чтобы посмотреть функции операторов такие как умножение, сложение и свойства normalized, и переписать код на C++ можно декомплировать .net библиотеку C:\Program Files\Unity\Editor\Data\Managed\UnityEngine.dll через ILSpay. Например, там есть расчеты умножения кватерниона (X,Y,Z,W) на эйлеровы углы (X,Y,Z), нормализация, сложение. Библиотеку это можно взять из Unity игр или установив движок Unity.
     
    Адреса позиции и углов обычно находятся рядом друг с другом.
×
×
  • Создать...

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

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