@CoinsDMG cmp инструкция работает с целыми числами, а у тебя float
Сообщения Promising
-
RE: Pocket Rogues 1 убийство = +1 лвл
-
Cheat Engine
Cheat Engine - универсальный инструмент для отладки
В этой статье описаны особенности программы и установка.
Cheat Engine, переводится как Чит Двигатель, Двигатель Обмана, и является по аналогии с игровыми "движками" инструментом для создания читов, cheat - значит обманывать (англ).
Это самая продвинутая и многопрофильная программа из существующих в этой области на данных момент, позволяющая изменять игры и приложения как угодно, если у вас достаточно знаний.
Хотите добавить новые правила в игру, изменить существующие, или просто сделать что бы пшеница на вашей виртуальной ферме росла быстрее? Всё это позволяет данная программа, но этим её возможности не ограничиваются.
Для профессиональных программистов данная программа может послужить отличным отладчиком, позволяя найти проблему в чужом, или своём продукте и исправить её на лету.
Как и другие подобные программы, эта так же позволяет исследовать код игры для дальнейших его модификаций и изменений извне (например, с помощью программ написанных на высокоуровневых языках, таких как C#, или С++).
Программа имеет поддержку lua и позволяет автоматизировать многие действия внутри себя с его помощью, поддерживаются плагины написанные на lua, которые могут включать dll написанные на других языках.Скачать программу можно с официального сайта, она распространяется бесплатно, если при установке возникают проблемы, стоит отключить антивирус, некоторые антивирусы и стандартный защитник windows (только на windows 10+) удаляет файлы программы при установке и установщик навечно зависает.
Интерфейс программы на английском, хотя бы минимальное понимание желательно, но есть неофициальные русификаторы, ссылки на которые приведены не будут, потому что часто эти русификаторы вызывают проблемы в работе программы.
Для работы программа при каждом запуске будет требовать повышения прав, что бы иметь возможность внедряться в чужие процессы.
При первом запуске появляется предложение пройти туториал и указать данные для автоматической публикации ваших работ на официальном форуме программы, которые можно пропустить. Если вы понимаете английский, стоит пройти туториал, он очень информативный и простой. -
Память процесса
В этой статье описывается общее устройство того как процесс использует память
Весь код процесса выполняется в его памяти, память процесса это выделенная область в оперативной памяти компьютера, которая может изменять свой размер динамически и начинается с загрузки .exe файла процесса при его запуске.
Память выделяется страницами, обычно минимальный размер страницы на windows это4096 байт
, то есть меньше этого значения быть не может при выделении. Когда выделяется память, просто говоря - для процесса резервируется больший участок в оперативной памяти.
У памяти бывают разные типы защиты, этим определяются типы памяти, которые могут быть использованы для сужения региона поиска в Cheat Engine, настройки предоставлены здесь:В полях сверху можно указать начальный адрес поиска и конечный, между которыми будет осуществляться поиск, а ниже можно указать типы памяти среди которых будет вестись поиск. Галочка означает что поиск будет вестись только по этому типу, отсутствие галочки - только без этого типа, а с квадратиком - и в том типе и в этом. Все регионы памяти могут иметь несколько типов защиты одновременно, основные типы защиты памяти:
Writable память - записываемая, та, которая позволяет записывать в себя новую информацию заменяя старую, обычно в этой памяти хранятся изменяемые значения.
Executable память - исполняемая, та, которая исполняется потоками проходящими по ней, в которой хранятся машинные коды, которые отображаются как ассемблерные инструкции, обычно она не Writable, но если приложение генерирует исполняемые инструкции на лету, как например Java приложения, тогда она будет Writable.
Readable память - читаемая, та, которая может быть прочитана. Этот флаг есть почти у всех регионов памяти.
Подробнее про CopyOnWrite можно прочитать здесь.
Если поток попытается сделать операцию с памятью которая не позволяет этого из за своего типа защиты, приложение будет закрыто с ошибкой. Помните об этом в дальнейшем. Посмотреть тип текущей страницы памяти с которой вы работаете можно через Cheat Engine, в нижней части окна отладчика:
Положение верхнего и нижнего окна (отслеживаемый адрес) не связаны, поэтому не забывайте перейти по адресу в нижнем окне на адрес верхнего, если вам нужно и не запутайтесь в них. Нижнее окно показывает значения, тип значений может быть изменён через контекстное меню:
Верхнее показывает машинные коды преобразованные в ассемблерные инструкции.
Вы можете выделить новую страницу в памяти процесса для своих нужд, сделать это можно через меню инструментов:
После выделения памяти через Cheat Engine, она будет иметь разрешения и на запись, и на чтение, и на исполнение, вы можете делать что угодно в этой памяти:
Size на изображении указан 1000, это 4096 в шестнадцатеричной системе счисления, потому что для примера я выделила одну страницу памяти.
-
Поиск значения
Статья демонстрирует как можно найти и изменить значение в памяти процесса с помощью Cheat Engine
Для начала работы вам понадобится Cheat Engine.
Если вы прошли встроенный в него туториал то уже знаете как искать значения. В этой статье рассмотрен пример на игре Terraria.Заходим в игру, и выясняем сколько здоровья у персонажа:
500 здоровья. Что бы найти это значение в Cheat Engine, сначала нужно подключиться к процессу игры. Для этого нажимаем переливающуюся разными цветами кнопку со значком монитора и лупы:
После нажатия появится окошечко выбора процесса, найдите в нём процесс игры, обычно, имеет название как .exe файл игры:
Или перейдите на вкладку Applications сверху и выбере там, по названию окна, после чего нажимайте кнопку Open, если вы планируете проводить отладку процесса, можете вместо этого нажать кнопку Attach debugger to process, это можно сделать и позже.
Если процесс успешно открылся, вы увидите его название над строкой поиска:
Теперь можно начинать поиск значения. Нужно найти значение 500, как указано в игре, столько здоровья у персонажа, но изначально неизвестно, какой тип у значения. Если в игре значение показывается как целое, или с плавающей запятой, оно не обязательно является таким, поэтому начните с простого и попробуйте искать в вероятном типе и размере.
В этой игре значение здоровья персонажа бывает больше чем 255, значит оно точно больше чем байт, двухбайтовые значения разработчики игр используют редко, поэтому начинайте поиск с 4 байт:
Впишите значение в строку поиска, расположенной под словом Value и нажмите кнопку First scan:
Если поиск прошёл удачно, слева будет показан список найденных значений такого типа и размера:
Что бы найти среди них конкретное значение, нужно уменьшить количество совпадений, для этого измените значение в игре, например позволив монстру стукнуть вашего персонажа:
Следите что бы значение не изменялось когда вы его ищите, поставьте игру на паузу.
Теперь введите отображаемое значение вместо первых 500 и нажмите кнопку Next Scan:При успешном поиске список значений изменится, в этой игре значение осталось всего одно сразу, но обычно требуется повторить процедуру изменения значения и отсеивания (Next Scan) несколько раз:
Для того что бы проверить, нужное ли это значение, добавьте его в таблицу, сделать это можно выделив значение нажав на него и нажав на кнопку со стрелочкой, или через контекстное меню которое появляется нажатием другой кнопки мыши на значение, (в нём же можно и изменить значение не добавляя в таблицу):
Если всё сделано правильно, значение появится в таблице:
Теперь попробуйте изменить значение, дважды кликнув на цифру 417 в графе Value, появится окно изменения значения (так же можно изменить значение не вызывая окна, просто выделив его и нажав ентер, набирать цифрами, для применения нажать ентер):
Введите желаемое значение и нажмите OK, значение должно измениться:
Перейдите в игру и посмотрите, изменилось ли значение в ней:
Если вы нашли верное значение, вы увидете изменения в игре, если значение не изменилось, стоит начать поиск заново, изменив тип значения на другой. Стоит попробовать типы 4 байта, float, double. Для начала нового поиска нажмите кнопку New Scan.
Вы можете управлять значением из таблицы, например запретить ему изменяться. Оно будет изменяться, но Cheat Engine будет возвращать его к выбранному вами. Для заморозки значения нажмите на квадратик в графе Active:
Теперь перейдите в игру и посмотрите на результат, значение должно возвращаться к выбранному после любых изменений, например нанесения урона персонажу.
Так же можно нажать справа от крестика и указать тип заморозки, стрелка вверх значит что значению можно увеличиваться, но нельзя уменьшаться, стрелка вниз - наоборот:
Вы можете изменять несколько значений выделив их и выбрав пункт в контекстном меню, или два раза кликнув на него.
-
Инструкции ассемблера и регистры процессора
В теме рассматриваются простые команды ассемблера, принцип работы и основные регистры процессора
Как написано в статье про типы данных, для компьютера всё состоит из едениц и нулей в выделенных областях памяти, исполняемый код не исключение, он состоит из байтов и может называться байткодом.
Компьютер выполняет вычисления указанные в байтовом коде и любая запущенная программа состоит из него. Написанная на любом языке программа в итоге конвертируется в байткод перед выполнением.Человеко-читаемое отображение байткода - ассемблер. Отладчик может прочитать байткод и показать его в виде ассемблерных инструкций, понятных человеку, а так же может давать возможность изменять этот код прямо в работающей программе, что бы корректировать указания даваемые компьютеру.
Cheat Engine обладает этими функциями и прежде чем они будут разобраны, изучите основные команды, регистры и структуру автоассемблера используемого Cheat Engine.Регистры:
Регистры процессора представляют собой временное хранилище данных для быстрой обработки и вычислений, вычисления большинства команд могут производиться только с регистрами, то есть выражение должно включать в себя регистр. Регистры состоят из частей, например регистр eax вмещает в себя 4 байта, 32 бита и состоит из нескольких частей:Как показано на этой картинке, регистр
eax
состоит из первой части, где 16 бит не обозначены отдельным подрегистром, и регистраAX
, размером 16 бит, как вы помните (2 байта), который в свою очередь состоит из двух частей по 8 бит (1 байт)AH
иAl
.
Данная информация нужна для понимания если вам нужно работать с разноразмерными значениями, но в основном вам будут встречаться значения размером 4 и 8 байт,rax
это 64 битная версия регистраeax
которая вмещает 8 байт и бывает в 64 битных приложениях.Основные регистры следующие, с указанием размера в байтах:
8 4 2 1 1 RAX EAX AX AH AL RBX EBX BX BH BL RCX ECX CX CH CL RDX EDX DX DH DL RSI ESI SI RDI EDI DI RBP EBP BP RSP ESP SP
В дальнейшем использовать для временного хранения данных вам следует все кроме ebp и esp, так как эти регистры могут использоваться для взаимодействия со стеком, о котором будет рассказано позже.
Помните что использовать 8 байтовые регистры можно только в приложениях 64 бит. Регистры имеют осмысленные названия, например ESP - Extended Stack Pointer (Расширенный указатель на стек). Расширенный он, грубо описывая, потому что архитектура эволюционировала постепенно, было 16 бит, существовал только SP, разработали 32 бит, добавили ещё 2 байта вперёд и так далее.
Подробнее про эти регистры можно почитать на английском тут.Команды ассемблера:
Команды ассемблера используются для операций со значениями расположенными в регистрах и памяти приложения.
Основные команды с синтаксисом Cheat Engine autoassembler которые пригодятся для понимания следующих статей, с примерами:mov
- переместить (скопировать) данныеmov eax, A //Поменстить в eax число 10 (A - шестнадцатиричная система) mov eax, #10 //Поместить в eax число 10 (#10 - десятичная система) mov eax, [адрес] //Переместить значение по адресу 4 байта в регистр eax mov [адрес], eax //Переместить значение из регистра eax 4 байта по адресу mov ecx, eax //Переместить значение из регистра eax в регистр ecx mov [адрес], al ///Переместить значение из регистра al 1 байт по адресу mov [адрес], [адрес] //Не правильно и работать НЕ БУДЕТ, все двойные операции только с регистрами.
add
- добавитьmov eax, 5 mov ecx, 4 add eax, ecx //Добавить ecx к eax, после этого eax = 9 add [адрес], eax //Добавить к значению по адресу eax 4 байта
sub
- вычестьmov eax, 5 mov ecx, 4 sub eax, ecx //Вычесть из eax ecx, после этого eax = 1 sub [адрес], eax //Вычесть из значения по адресу eax 4 байта
inc
- увеличить на 1
dec
- уменьшить на 1inc [адрес] //Увеличить значение по адресу на 1 dec eax //Уменьшить eax на 1
mul
- умножить, использует регистры и операнд. Регистр eax умножается на операнд и результат помещается в eax, остаток помещается в edxmov eax, 5 mov ecx, 4 mul ecx //Результат, eax = 20, edx = 0
div
- разделить, использует регистры и операнд. Значение из двух частей в eax:edx (записывайте edx 0 если хотите делить значение в рамках размерности 4 байт) делится на операнд и результат помещается в eax, остаток помещается в edxmov eax, 8 mov edx, 0 mov ecx, 4 div ecx //Результат eax = 2, edx = 0 mov eax, #10 mov edx, 0 mov [адрес], 5 div [адрес] //Результат eax = 2, edx = 0
xor
- побитовое исключающее ИЛИ, но для начала достаточно знать что это команда часто используется для обнуления регистров компиляторами, сравнивая их самих с собой, так как она обычно занимает меньше байткода чем напримерmov eax, 0
mov eax, 5 xor eax, eax //eax = 0 mov rax, 8 xor rax, rax //rax = 0
lea
- получить адрес значения, вместо него самого, может использоваться во многих ситуациях и вычислениях с регистрами, некоторые будут рассмотрены в следующих статьях.//Допустим адрес = A040D8, значение по адресу 5 mov eax, [адрес] //eax = 5 lea eax, [адрес] //eax = A040D8
nop
- ничего не делающая инструкция, занимает место 1 байт, или столько, сколько указано, эта инструкция может быть использована для замены на неё других инструкций, что бы отключить их выполнение, в следующих статьях есть примеры.nop //Ничего не произошло, занимает 1 байт nop 5 //Ничего не произошло, занимает 5 байт
Справочник со всеми командами на английском
Структура выполнения кода:
Байткод выполняется последовательно, ассемблерные инструкции тоже. Поток проходит по порядку с инструкции на инструкцию и выполняет их. Его положение может быть изменено с помощью некоторых команд, специальный регистрEIP
отображает положение потока, текущий адрес на котором он находится:Скриншот из отладчика Cheat Engine. В этом примере можно заметить, слева адрес инструкции, дальше байты инструкции (байткод), а справа интерпретация в виде ассемблерного кода который можно прочитать.
Инструкцияjmp
позволяет перемещать поток на определённое количество байт вперёд, или назад. Cheat Engine сам посчитает байты, вам нужно только указать адрес:В этом примере инструкция
add eax, ecx
выполняться не будет, вместо этого сразу будет выполнятьсяsub eax, ecx
.Другой пример:
В этом примере поток останется в бесконечном цикле и программа зависнет. Для того что бы безопасно управлять положением потока используются условные переходы, рассмотренные в следующей статье.
-
Потоки
В этой теме описывается что такое потоки в общих чертах
Потоками называются сущности исполняющие машинный код в участках памяти приложения, одно приложение может иметь множество одновременно работающих потоков, исполняющих код в разных местах.
У каждого потока есть стек и собственные значения в регистрах. Стек и регистры служат для временного хранения данных для удобной их обработки. Стек находится в выделенной памяти приложения и у каждого потока он свой.Потоки виртуальны, то есть они не привязаны и не ограничены количеством ядер процессора и прочим, может существовать сколько угодно потоков, пока они влезают в ограничения по памяти выделяемой для приложения.
В Cheat Engine посмотреть список работающих потоков можно в окне отладчика через меню View:
После этого появится окно отображающие потоки, у каждого потока можно развернуть выпадающий список и посмотреть на контекст этого потока, контекстом называются его регистры и флаги:
Потоки имеют числовой идентификатор по которому они могут быть найдены, закрыты, заморожены, и тому подобное.
С помощью Cheat Engine вы можете создать новый поток для выполнения своего кода. Выделим память и напишем там простую функцию, о функциях подробнее будет рассказано в следующих статьях:
Код задан, этот код берёт число 5, добавляет его к самому себе, увеличивает на 1 и вычитает из результата 4, результат записывается по адресу
08600000
. В нижнем окне показано текущее значение адреса, оно является нулевым. Что бы код выполнился нужно вызвать поток на него. Так как это функция, она имеет командуret
что бы поток вернулся после выполнения.
Для создания потока, выделите первую команду функции и в меню инструментов выберите создание потока:Вас спросят на каком адресе создать поток, если вы выделили определённую инструкцию, адрес автоматически подставится в это окно:
После этого появится окно с вопросом какой параметр задать потоку перед запуском, который попадёт в регистры. Оставьте его 0, в данном коде не нужно задавать предварительные значения регистрам:
После того как вы подтвердите создание потока, он выполнит функцию и вернётся, значение в адресе изменится:
Так как значение находится рядом с инструкциями, верхнее окно попыталось распознять в нём инструкции и создало непонятную мешанину. Для того что бы исправить отображение просто перейдите на адрес начала функции используя стрелочки на клавиатуре для точной корректировки позиции, или укажите адрес самостоятельно нажав
Ctrl+G
:Создание потоков может быть автоматизировано с помощью команд скриптинга, которые рассмотрены в следующих статьях.
-
Изменение инструкций ассемблера
В этой статье описывается процесс изменения инструкций автоассемблера на другие
В статье использованы инструкции найденные в предыдущей статье:
Загрузите сохранённую таблицу Cheat Engine и подключите его к игре. Если инструкции в вашей игре статичные и не изменились, то вам не нужно искать их снова. Откройте code list и проверьте инструкции, заменив их нопами и восстановив.
Для того что бы изменять инструкции, нужно открыть их в окне отладчика, сделать это можно через контекстное меню, или дважды кликнув по ним:После этого появится окно отладчика с подробностями:
Вы можете заметить что сверху и слева в этой игре Cheat Engine распознал адрес функции и смещение до текущей инструкции от начала функции. Если вы хотите сохранить этот адрес для дальнейшего использования, нажмите на нужную инструкцию второй кнопкой мыши для вызова контекстного меню и выберите там:
После этого в буфере обмена окажется
Terraria.Player::Hurt+1201
, вы можете записать это в удобное место и в дальнейшем перейти на этот адрес в окне отладчика нажавCtrl+G
, или через контекстное меню.Для изменения инструкции дважды кликните на неё, откроется окно редактирования:
Если вы читали статью о командах ассемблера, то скорее всего понимаете что делает эта инструкция, она вычитает из значения здоровья персонажа число находящееся в регистре eax, то есть в eax находится урон нанесённый персонажу.
Если вы измените sub на add, тогда персонаж будет лечиться вместо получения урона, для наглядности попробуйте изменить её на mov, тогда персонаж будет получать здоровье равное значению полученного урона:Перейдите в игру и посмотрите на результат:
Получив 1 урона, персонаж получил 1 здоровье:
Восстановите оригинальную инструкцию заменив mov на sub.
Таким образом вы можете изменять одну линию в коде, если создаваемый вами код больше чем оригинальная инструкция, он займёт место следующей и Cheat Engine спросит, заменить ли оставшуюся часть от инструкции nop, если вы не замените, то скорее всего получите ошибку игры, из за неправильных инструкций. Если ваш код меньше - тогда выбирайте замену нопами, если вы восстанавливаете оригинальную инструкцию из меньшей и дальше уже есть нопы, отказывайтесь от замены нопами, что бы код восстановился полностью. -
Поиск неизвестного значения
В теме показано как искать неизвестное значение
Рассмотрены некоторые особенности поиска неизвестных значений и координат
Поиск неизвестного значения применяется, если вы не знаете точно, каким является значение, например, если оно отображено просто заполняющейся полоской, или в странном формате (например как формат времени).
В этой статье показано как найти координаты персонажа на примере игры Terraria.
Сначала откройте игру и подключитесь к процессу с помощью Cheat Engine, как показано в предыдущей статье:Теперь перейдите в игру, так как неизвестно, какие у персонажа координаты, и когда они увеличиваются, а когда уменьшаются, предположим что увеличиваются они если персонаж перемещается вправо, а уменьшаются влево. Для удобства поставьте в игре ограничительные блоки:
Установите персонажа впритык к самому левому:
Поставьте игру на паузу и перейдите в Cheat Engine, там выберете поиск неизвестного значения из списка:
Нажмите First Scan, не появится никаких значений слева, но должно показать общее их количество:
Теперь перейдите в игру и передвиньте персонажа вплотную к следующей отметке:
Перейдите в Cheat Engine и выберите Scan Type как Increased value (увеличенное значение):
После этого нажмите Next Scan, если вы всё сделали верно и поиск успешен то сверху появятся значения и их общее количество (около Found) уменьшится:
Значений слишком много и нужно провести отсеивание, для этого передвигайте персонажа и выбирайте тип следующего поиска в соответствии с этим, переместите персонажа снова впритык к левому ограничителю:
В Cheat Engine выберите тип поиска Decreased value (уменьшенное значение):
После этого нажмите Next Scan:
Если вы всё сделали верно то количество значений должно уменьшиться. Продолжайте перемещать персонажа вправо и влево производя соответствующий отсев, выбирая "Увеличилось" если персонаж стоит правее чем при прошлом поиске, и "Уменьшилось" если левее. Если вы совершили ошибку, например перепутали стороны поиска и поняли это, не обязательно начинать новый поиск, вы можете вернуться к результатам предыдущего отсева нажав Undo Scan.
Когда значений останется меньше и вы заметите что их количество от поиска к поиску уменьшается слабо, стоит использовать отсев с указанием "Не изменилось", для этого сдвиньте персонажа в определённую сторону, выберите соответствующий поиск (уменьшилось/увеличилось) и проведите его, после этого вернитесь в игру и не перемещайте персонажа с позиции последнего поиска.
Позвольте ему немного постоять на месте и перейдите назад в программу, выберите тип поиска Unchanged value, это значит что вы хотите что бы Cheat Engine убрал все значения из списка которые изменились с прошлого поиска и оставил лишь те которые не изменились, если персонаж не двигался с прошлого поиска то его значение должно попадать в диапазон:Произведите поиск:
Количество значений довольно заметно сократилось. Теперь, не перемещая персонажа продолжайте возвращаться в игру, а потом в Cheat Engine и нажимать Next Scan с выбранным Unchanged value, пока количество значений ещё сильнее не уменьшится:
Значений всё равно много, что бы их уменьшить стоит прибегнуть к сравнению с первым поиском, именно для этого персонажа устанавливали вплотную к ограничителю из блоков. Поставьте персонажа в точно такое же положение как при первом поиске:
Перейдите в Cheat Engine и поставьте галочку на Compare to first scan, тогда при следующем нажатии Next Scan программа будет сравнивать значения не с результатом прошлого поиска, а с результатом самого первого:
Выберите тип Unchanged value, потому что персонаж стоит в той же позиции что и при первом поиске и произведите отсев:
Значений стало меньше, но всё равно ещё слишком много. Не забудьте снять галочку с Compare to first scan когда сдвините персонажа с позиции. Что бы ещё уменьшить их количество, попробуйте сделать что то необычное. Поиск производился для координаты X персонажа, то есть для горизонтального положения, поэтому попробуйте уменьшить другую координату, опустите, или поднимите его:
После этого произведите отсев с параметром "не изменившееся":
Значений стало намного меньше, но всё равно ещё слишком много. Что бы ещё уменьшить их количество, попробуйте увести персонажа далеко вправо от позиции начального поиска:
И проведите отсев увеличившегося значения:
Значений стало ещё меньше, вернитесь в изначальную позицию и произведите отсев уменьшившегося значения:
Количество значений не изменяется, это значит что дальше отсеять уже нельзя. Все эти значения относятся к разным объектам на экране, позиция персонажа, позиция камеры, позиция шляпы персонажа и прочего, поэтому их так много. Такая ситуация возникает довольно часто и что бы найти нужное значение координаты X персонажа - нужно проверять их.
Выберите все значения и добавьте их в таблицу, для этого нажмите на любое значение в окне поиска и нажмите
Ctrl+A
на клавиатуре что бы выделить все значения, после чего нажмите на красную стрелочку, все значения переместятся в таблицу:Для нахождения нужного значения, выделяйте и замораживайте группы значений, что бы они не могли изменяться и пробуйте перемещать персонажа в игре. Для заморозки значений выделите несколько из них мышкой, для этого нажмите на первое, потом зажмите клавишу шифт и нажмите на следующее, выделятся все значения между ними включая их самих:
Для того что бы быстро заморозить, или разморозить значения, нажмите пробел находясь в активном окне Cheat Engine:
Перейдите в игру и попробуйте переместить персонажа вправо, или влево:
Персонаж перемещается, но дёргается небо и облака, значит это не нужные значения. Удалите выделенные значения нажав клавишу
Del
на клавиатуре, если они вам не нужны, или просто снимите с них заморозку нажав пробел. Выделите следующую группу значений и повторите процедуру.
Для удобства и быстроты поиска, самый эффективный способ это выделять и замораживать сразу половину от всех значений в таблице, проверять в игре, может ли персонаж перемещаться по X, если искомое значение будет среди них и он не сможет, вы сможете сразу удалить другую половину значений в таблице и повторить процедуру с половиной оставшихся значений:После нескольких повторений осталось лишь несколько значений:
Так как персонаж может перемещаться, значит верхние значения не нужные, удалите их:
Теперь можно поочерёдно замораживая значения и проверяя игру, найти нужное:
Остальные значения можно удалить:
Сравним значение в позиции около первого ограничителя и около второго:
И у второго:
Вы можете записать эти числа и в дальнейшем, после перезапуска игры без труда найти нужное значение с помощью поиска точного значения из предыдущей статьи. Как сделать что бы значение не нужно было каждый раз искать рассказано в следующих статьях.
Теперь вы можете заметить, что значение координат выглядит странным слишком большим. Можно проверить свои подозрения, попробовав изменить его тип, как программа читает его из памяти, для этого два раза кликните на "4 Bytes" в строке Type, появится окно выбора типа:
Выберите тип float и посмотрите как изменится внешний вид значения:
Посмотрите как оно выглядит в первой и второй позициях:
Теперь оно приняло читаемый вид и можно попробовать вычислить расстояние, которое занимает один блок в игре, посчитав блоки между столбиками и разделив разницу между вторым и первым значением на это количество, получится
(51340 - 51280) / 4 (блоков 5, но персонаж занимает 2 блока, потому -1 блок будет 4) = 15
Для проверки попробуем вычесть из значения около правого столба 30 и записать его, посмотрев, на сколько блоков переместится персонаж, производить арифметические операции можно прямо в строке изменения значения:Персонаж переместился ровно на 2 блока влево, значит всё посчитано верно.
Это было математическое отступление, а теперь нужно найти вторую координату, что бы перемещать персонажа не только вправо и влево, но и вверх и вниз.
Можно начать новый поиск, но сначала попробуйте добавить значение по адресу расположенное прямо следующим за этим, так как координаты обычно располагаются рядом. Есть разные виды расположения координат,x y
,x y z
,x z y
, и прочие, это двухмерная игра, поэтому стоит попробовать проверить первый тип, для этого продублируйте значение в таблице, выделив его, нажавCtrl+C
и затемCtrl+V
, после того как вы сделаете это, появится окно спрашивающее, как добавить значение:В нём можно указать на сколько сместить адрес, чем заменить и прочее, сейчас просто нажмите кнопку Paste ничего не меняя, значение появится в таблице:
Для удобства назовите первое значение "X", для этого кликните дважды на No description и введите свой текст.
Что бы проверить, находится ли координата Y поблизости, нужно изменить адрес только что добавленной записи. Для этого нажмите на адрес в графе Address второго значения и добавьте к адресу 4, так как тип float занимает 4 байта, а получить нужно значение идущее следующим:
Как только вы введёте + 4, вам станет видно какое значение располагается по этому адресу, если оно выглядит адекватным, тогда можно нажать OK и адрес в таблице изменится. Если бы поиск начинался с Y, тогда для получения X нужно было бы вычитать 4, а не добавлять. Помните что адрес считается в байтах в шестнадцатеричной системе счисления.
Для проверки попробуйте изменить значение, например добавив к нему 60 (4 блока):
Персонаж переместился вниз, значит координата Y тем больше, чем ниже персонаж в этой игре (обычно наоборот).
С этими значениями вы можете перемещать персонажа по всей карте в любое место. Как это делать удобнее можно узнать из следующих статей. -
Поиск инструкций работающих с адресом
В теме описанао как найти инструкции работающие с адресом, а так же использование nop для отключения инструкций
Для начала вам понадобится значение, для которого вы хотите выполнить поиск инструкций, возьмём значение здоровья персонажа найденное в статье по поиску значения:
Cheat Engine предоставляет два вида обнаружения инструкций, по обращению и по записи. По записи - это те инструкции которые записывают в адрес значение, например уменьшают здоровье персонажа при получении урона. По обращению - это все инструкции, и те что записывают и те что читают, например инструкция считывающая значение что бы нарисовать его на экране в виде сердечек.
Для поиска на запись, вызовите контекстное меню, кликнув на значение в таблице второй кнопкой мыши и выберите этот пункт, или нажмите F6 выделив элемент в таблице:Когда вы нажмёте на этот пункт, если отладчик не подключен то программа спросит вас, подключить ли отладчик к игре, подтверждайте и увидите вот такое окно:
Это окно будет ожидать записи по адресу и показывать что записало в него. Для того что бы там появились новые инструкции, перейдите в игру и измените значение здоровья персонажа, полуичв урон, или вылечившись:
После этого перейдите в Cheat Engine и посмотрите на инструкции в окне:
Появилось две интструкции, описанные в предыдущей статье, первая вычитает из адреса здоровья число находящееся в регистре eax, а вторая увеличивает здоровье на 1.
Значит, первая инструкция это урон при касании врага, а вторая это инструкция отвечающая за постоянную регенерацию персонажа.
Что бы прекратить отслеживание новых инструкций нажмите кнопку Stop, после чего добавьте найденные инструкции в лист сохранённых инструкций, что бы в дальнейшем использовать их, для этого выделите обе инструкции таким же способом как выделяете записи в таблице и нажмите кнопку Add to the codelist:После нажатия инструкции появятся в новом окне:
Закройте окно поиска инструкций нажав клавишу Close, или крестик:
Теперь вы можете сохранить таблицу в любое удобное для себя место с помощью этой кнопки:
Если вы закроете окно с сохранёнными инструкциями Code List, вы можете снова открыть его, нажав на надпись Advanced options в левом нижнем углу главного окна Cheat Engine:
В большинстве игр инструкции находятся на статических адресах и после перезапуска игры сохраняются, таким образом вам не придётся заново искать значения что бы найти их.
Перейдите в окно Code List и выберите инструкцию вычитающую здоровье персонажа:
Вызовите контекстное меню для неё и выберите "Заменить ничего не делающим кодом" (нопами nop):
Перейдите в игру и проверьте, уменьшается ли здоровье персонажа при уроне от тех же источников. Если нет, значит вы всё сделали правильно. В отличии от заморозки, замена нопами полностью отключает действие инструкции, таким образом здоровье персонажа больше не будет уменьшаться при получении урона от врагов.
Что бы восстановить инструкцию, снова нажмите на неё вызвав контекстное меню и выберите "Восстановить оригинальный код":
Таким образом вы можете предотвратить изменение значений и вам не нужно каждый раз заново искать значение. О более продвинутых операциях с инструкциями описано в следующих статьях.
-
Стек
В этой теме рассказано о том что такое стек потока
Стек потока представляет собой временное хранилище данных для работы с ними. Данные могут быть помещены в стек и достаны из него с помощью разных инструкций ассемблера. Стек на самом деле является просто выделенной памятью.
Поток получает странницу памяти представляющую стек при создании и хранит текущее смещение (адрес) стека в регистре esp.
Изначально стек пустой, то есть имеет нулевые значения. Для взаимодействия со стеком есть специальные инструкции:push
- Сдвинуть адрес стека (вычесть из esp) и записать в него значение. В 64 битных процессах сдвигает стек на 8 байт, в 32 битных процессах на 4 байта.push 5 //Сдвигает стек (значение адреса в esp) и записывает по адресу стека число 5 push [адрес] //Тоже самое, но загружает значение из адреса push eax //Тоже самое, но загружает значение регистра
pop
- Прочитать из стека и сдвинуть адрес стека (добавить к esp) и записать в него значение. Правила такие же как у push по разрядности процессов.push 5 pop eax //Выгружает из стека число 5 в регистр eax, теперь в нём число 5 push 6 pop [адрес] //Выгружает из стека число 6 по адресу
Использование обычных команд для работы со стеком
//Аналог push 5, это то что он делает sub esp,4 mov [esp],5 //Аналог pop eax, это то что он делает mov eax,[esp] add esp,4 //Загрузка и чтение нескольких разных значений из стека push 5 push 4 push 8 mov eax,[esp] //eax = 8 mov ecx,[esp+4] //ecx = 4 mov ebx,[esp+8] //ebx = 5 add esp,#12 //Или add esp,C в шестнадцатеричной системе счисления //Пример замены значения в стеке и выгрузки командой pop push 5 mov [esp],8 pop eax //eax = 8
В Cheat Engine стек можно увидеть при выполнении отладки процесса, о которой рассказано в следующих статьях.
-
Хоткеи для значений
В статье описано как пользоваться хоткеями для записей в таблице
Описание установки хоткеев и упрвление таблицой, создание заголовков, активация нескольких значений.
Для каждой записи в таблице, адреса, скрипта, группы и прочего - могут быть утсановлены хоткеи, хоткеи это горячие клавиши, при нажатии которых значение каким либо образом изменяется.
Для примера возьмём координаты в игре Terraria найденные в предыдущей статье:Для установки хоткея на значение, нажмите на него второй кнопкой мыши что бы вызвать контекстное меню:
Выберите Set Hotkeys, должно появиться окно установки хоткеев, так же можно это сделать не вызывая контекстное меню, выделив значение и нажав
Ctrl+H
:Что бы создать новый хоткей нажмите кнопку Create hotkey:
После этого у вас появится возможность выбрать клавиши на которые будет производиться действие, нажмите мышкой в поле слева от кнопки Clear и нажмите на клавиатуре поочерёдно желаемые клавиши, или одну клавишу для хоткея. После того как вы выбрали клавиши, нажмите на любой интерактивный элемент в окне, например на поле над кнопкой Apply, что бы снять выделение с поля выбора клавиш.
Если вас не устраивает сочетание которое вы выбрали, можно нажать кнопку Clear и повторить процесс:теперь вы можете выбрать действие, которое будет производиться при нажатии выбранного сочетания клавиш:
Здесь вы можете выбрать заморозку значения, разморозку значения, изменение его на какое либо определённое, уменьшение, увеличение, заморозка с параметрами. Выберем увеличение значения на 60 (4 блока):
Для применения изменений нажмите кнопку Apply, вы увидите свой хоткейи добавленным:
Вы можете добавить ещё хоткеев, или изменить этот, выделив его и нажав кнопку Edit Hotkey, удалить запись с хоткеем можно через контекстное меню:
Закройте окно с хоткеями нажав OK и перейдите в игру, для проверки хоткея. Нажмите назначенное сочетание клавиш:
При каждом нажатии персонаж перемещается на 4 блока вправо, значит всё работает правильно.
Назначив хоткеи на оба адреса и X и Y, можно перемещать персонажа по карте в любую сторону.
Если адресов много, и нужно сразу все их разморозить, или заморозить на один хоткей, неудобно было бы назначать хоткей отдельно каждому адресу, для этого существуют группы. Группой может являться любая запись в таблице, а так же можно создать заголовок группы отдельно, через контекстное меню, нажав на пустом месте таблицы:Выберите пункт Create Header в контекстном меню, должно появиться окно, спрашивающее, как назвать заголовок, выберите желаемое название и нажмите OK, дальше появится окно, которое спросит, хотите ли вы, что бы ваш заголовок поддерживал адрес, выберите нет, если вам не нужно задавать ему адрес:
После этого заголовок должен появиться в таблице:
Теперь нужно перенести в него записи X и Y. Для этого выделите обе записи X и Y и перетащите мышкой ровно на заголовок, для того что бы не промахнуться, перетащите их мышкой ровно на середину квадратика активации заголовка, если вы всё сделали правильно, значения спустятся под заголовок:
Теперь можно настроить как заголовок будет влиять на вложенные значения, для этого зайдите в контекстное меню заголовка и наведите указатель на Group config:
Тут вы можете настроить параметры заголовка, отметьте галочками второй и третий пункт, которые гласят "Активация этой записи активирует дочерние записи" и "Деактивация этой записи деактивирует дочерние записи", таким образом, когда вы заморозите заголовок, заморозятся и адреса координат X, Y:
Для проверки заморозьте/разморозьте группу и посмотрите, повторяют ли вложенные значения за ней:
Назначьте заголовку хоткей для заморозки и разморозки на разные клавиши, или на одну, (для одной выберите Toggle freeze) :
Перейдите в игру и попробуйте нажимать клавишу и наблюдайте что происходит, с помощью этого хоткея можно заставить персонажа зависнуть в воздухе на одном месте, или стоять не отскакивая среди толпы врагов:
Если вам кажется что хоткей, или заморозка работает слишком медленно, вы можете зайти в настройки программы и изменить интервал заморозки и хоткеев:
Чем меньше число, тем быстрее будет восстанавливаться значение к замороженному.
Чем меньше задержка, тем чаще будет срабатывать хоткей пока зажата клавиша.
Так же в этом меню настроек вы можете задать разные глобальные хоткеи для самой программы, например хоткей для заморозки и разморозки процесса, что позволит вам ставить игры на паузу, которые не имеют такой возможности и может быть полезным при поиске изменяющихся значений:Там есть и множество других полезных функций, облегчающих поиск и многое другое, вы можете сами изучить этот список.
-
Оглавление
С чего начать новичку
Статья содержит информационное-оглавление полезное для новичков, разделы расположены в последовательном порядке.
- Инструменты:
- Отладка приложения:
- Создание скриптов autoassembler:
- Числа с плавающей запятой:
-
Process Monitor
Process Monitor универсальный шпион за программами
В статье описаны возможности программы
Программа позволяет следить за всеми остальными работающими в данный момент на компьютере, или за какой-то конкретной. Она отслеживает и показывает все действия совершаемые процессом в системе, что он читает из реестра, что он записывает, какие он создаёт и удаляет файлы. Всё это удобно сохраняется и просматривается.
Программа может иметь самые разные использования, из простейших - посмотреть, в какое место нужная программа, или игра сохраняет файл настроек.
Подробности использования и ссылка на скачивание находятся в официальной статье на страничке mdsn.
Эта программа не обязательна для выполнения примеров из следующих статей. -
Типы данных
В статье описаны типы данных и что это такое
Компьютер работает со значениями, а значения могут иметь разный размер и тип, или могут иметь одинаковый размер, но разный тип.
Все значения записываются в памяти с помощью едениц и нулей, то есть - в двоичной системе исчисления, эти еденицы называются битами (бит). В одном байте (байт) 8 бит, с помощью восьми бит, по разному их комбинируя, можно записать 256 разных разных состояний, поэтому у одного байта максимальное значение которое он может содержать это 255 (считается с нуля, вместе получается 256 состояний).Значения могут быть signed (может быть отрицательным) и unsigned (не может быть отрицательным), в зависимости от того что нужно программе. Их размерность от этого не меняется, лишь добавляется возможность отрицательных значений. Например у signed байта минимальное значение которое он может содержать -127, а максимальное 127.
Что бы записать значения больше чем 255, используются несколько байт. Максимальное unsigned значение из двух байт (16 бит) составляет 65535.
Чем больше бит использовано, тем больше можно записать, 8 байт позволяют записывать огромные объёмы данных.Для чисел с плавающей запятой используется похожая система, но из за того что количество состояний ограничено, появляется погрешность, эта погрешность существенна только для типа float, double использует 8 байт и его погрешность незначительна. Все типы с плавающей запятой по умолчанию signed.
Пример погрешности float:
При попытке записать5.04
во float 4 байта, в итоге получим5.039999962
.Помните что тип определяет лишь то как будет считано, или записано значение. Для компьютера типа не существует и существуют лишь гигантские массивы двоичных данных. Можно указать компьютеру прочитать значение с середины нужного, захватив кусок от другого, и получить полную ерунду, поэтому, при отладке нужно помнить о том что определение типа это задача самого пользователя.
При переполнении значения, например если попытаться добавить к байту в котором уже значение 255 ещё 1, происходит возвращение значения к его противоположному концу, в данном случае получится 0, если добавить 2 то получится 1 и тому подобное.
В Cheat Engine разные типы именуются в следующем порядке:
- byte - 1 байт, 8 бит
- word - 2 байта, 16 бит
- dword - 4 байта, 32 бит
- qword - 8 байт, 64 бит
С плавающей запятой:
- float - 4 байта, 32 бит
- double - 8 байт, 64 бит
С помощью значений можно описать любую информацию. Если вы открывали Cheat Engine то уже могли заметить что там есть тип String, это строковый тип, который читает значения из памяти и переводит их в текст. Существует множество различных кодировок текста, для кодировки букве присваивается номер, а потом этот номер записывается как значение. При чтении строки из памяти всё происходит наоборот, читается номер и ковертируется в понятный человеку символ.
Например слово "hello" это набор байт со значениями 104 101 108 108 111 в кодировке ASCII.
В Cheat Engine значения могут быть отображены в десятичной, или в шестнадцатиричной системе счисления. Шестнадцатиричная система счисления имеет максимальное значение 15 (F), вместо 9, для простоты понимания, когда мы начинаем добавлять, или менять цифру в десятичной системе - начинается новый десяток, в шестнадцатиричной так-же, сначала идут значения0 1 2 3 4 5 6 7 8 9 A B C D E F
, а потом добавляется10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C...
, так же как двоичная система имеет лишь 0 и 1, и 10 начинается уже после 1.0, 1, 10, 11...
Адреса памяти процесса обычно записываются в шестнадцатиричной системе, вам не нужно учиться считать в этих системах что бы работать с ними, главное это понимать принцип.
-
Синтаксис и команды
Синтаксис и команды скриптов в Cheat Engine.
Скриптовой язык в Cheat Engine в основном позволяет создавать и внедрять в игру ассемблерный код на ходу, и выгружать его из игры восстанавливая оригинальный код.
Окно скриптинга может быть открыто через окно отладчика, или сочетанием клавиш
Ctrl+A
в этом окне:После открытия вы увидите следующее окно:
В нём можно написать скрипт и нажать кнопку
Execute
что позволит выполнить скрипт. Что бы добавить скрипт в таблицу и сохранить его, вам сначала нужно добавить в него определённые команды, а именно две команды обозначающие разделы, которые будут выполняться при включении и выключении скрипта[ENABLE]
[DISABLE]
:Эти команды обозначают правила для включения и выключения скрипта. После их добавления можно добавить скрипт в таблицу с помощью контекстного меню:
Если всё сделано верно, скрипт появится в таблице и окно редактора можно закрыть:
Теперь вы можете снова открыть редактор, но уже для конкретно этого скрипта в таблице. Для этого дважды кликните по нему в графе
Value
, или откройте редактор через контекстное меню:Откроется редактор для конкретно этого скрипта, вы можете сохранить изменённый скрипт нажав кнопочку
OK
:Основные команды которые могут пригодиться:
Запись данных по адресу, необходимо указывать размерность:
//db - byte //dw - word //dd - dword //dq - qword (Адрес): db/dw/dd/dq(размерность) (число) //Пример, записать по адресу 0087745A подряд 12 байт, сначала 0, дальше 5, потом 7. 0087745A: dd 0 5 7 //Пример, записать по адресу метки label подряд 4 байта 1, 7, 10, 2 label: db 1 7 A 2
Каждая метка обозначает после себя регион памяти все метки в котором будут относиться к ней, если они уже не определены в другом месте, или не являются настоящим адресом.
//По адресу 0087745A располагается метка label, метка label нигде не определена, //значит она определяется и обозначается как место в скрипте после добавления. //Таким образом в данном примере label идёт в зоне 0087745A, сразу после него и указывает на тоже самое место, //то есть далее использовать label будет тоже самое что указать 0087745A: 0087745A: label: dd 0 //В следующем примере, указано что после 0087745A выделено 4 байта со значением 0, //зарезервировано командой dd 0, получается, метка будет указывать на следующие 4 байта после первых идущих в 0087745A: 0087745A: dd 0 label: dd 0
Метка может быть зарегистрирована в текущем скрипте, или даже объявлена глобально для использования из других скриптов.
label(lack)
зарегистрировать метку lack для текущего скрипта.
registersymbol(lack)
зарегистрировать метку lack глобально.
unregistersymbol(lack)
снять регистрацию с метки lack, обычно используется в секции[DISABLE]
.Пример скрипта, который записывает при включении по адресу 0087745A число float 4 байта 5, а при выключении int32 0:
С помощью скрипта вы можете легко выделить память и записать в неё значения. Выделяется память с помощью команды
alloc(newmem, 1000)
, эта команда выделяет новую память как минимум размером 1000 и создаёт для неё метку newmem, которая аналогична адресу выделенной памяти.Пример скрипта в котором выделяется новая память и в неё записывается значение, после выключения скрипта память освобождается командой
dealloc(newmem)
:Мы можем зарегистрировать newmem что бы получить возможность добавить эту метку как адрес в таблицу и увидеть значение:
Добавьте адрес newmem в таблицу, нажав на кнопку
Add Address Manually
:Включите скрипт нажав на квадратик слева от него, если всё сделано верно вы увидите значение записанное в память, не забудьте что Cheat Engine должен быть подключён к какому то процессу:
Значение float, измените его тип дважды кликнув на
4 Bytes
в столбикеType
что бы оно отображалось корректно:Более продвинутые команды и примеры скриптов рассмотрены в следующих статьях.
-
FPU
О том что такое FPU и его команды, обзор принципов взаимодействия
Fpu это математический сопроцессор который позволяет легко работать с числами с плавающей запятой и с обычными числами, совершать операции типа умножения и деления. Он может работать с любыми значениями 4 и 8 байт размера и любыми типами, float, double, int32, int64.
Все операции Fpu производятся в его стеке, в который сначала нужно загрузить значения, после вычислений значения нужно выгрузить если вам нужно получить результат и что бы не портить стек, если вы делаете инъекцию в код игры и она использует fpu.Некоторые команды сопроцессора:
//Если команда не имеет *, значит она работает с числом в стеке и не принимает переменных. //Почти все команды могут быть использованы на регистрах стека fpu с уже загруженными значениями, например fld st(0) продублировать последнее загруженное значение, или fadd st(0), st(1), сложить два последних загруженных значения в стеке и тому подобное. //Для выгрузки значения из стека вникуда используйте fstp st(0) //Почти все команды с f поддерживают вариант с fi, например fadd - fiadd, что указывает сопроцессору что сложение надо производить сначала сконвертировав число в число с плавающей запятой, например используйте fiadd если добавляете целое число int32. //Команды загрузки и выгрузки fld * - Загрузить вещественное число fild * - Загрузить в стек целое число fst * - Скопировать из стека в переменную fstp * - Выгрузить из стека в переменную fist * - Скопировать из стека в переменную и преобразовать в целое fistp * - Выгрузить из стека в переменную и преобразовать в целое fldpi - Поместить в стек число Пи fldz - Поместить 0 fld1 - Поместить 1 //Команды арифметический операций fadd * - Складывает значение в стеке и переменную fsub * - Вычитает из значения в стеке переменную fsubr * - Вычитает из переменной значение в стеке, и помещает в стек. fmul * - Выполняет умножение числа в стеке на переменную fdiv * - Выполняет деление fdivr * - Делит переменную на число в стеке и помещает результат в стек. fsqrt - Извлекает квадратный корень из числа в стеке. fabs - Убирает минус у числа в стеке (делает положительным) //Команды проверок fcom * - Сравнить значение в стеке с переменной ftst - Сравнить с нулём fstsw ax сохраняет флаги в приёмник (ax) sahf загружает флаги после команды выше.
Рассмотрим пример использования FPU в скрипте для конвертации в разные типы, из int32 во float и double:
-
Функции
В этой статье описано что такое функции
Функциями в ассемблере называются участки кода, на которые поток может переместиться и после выполнения вернуться с помощью специальной команды
ret
не используя jmp на конкретный адрес. Таким образом функции могут быть вызваны из любого места что делает их универсальными.Для перемещения в функцию используется команда
call
, для возврата из функции командаret
. Значение результата функции обычно передаётся через регистр eax, то есть функция заполняет его значением результата, но может и любым другим способом.call
- Вычитает из адреса стека 4, или 8 (в зависимости от разрядности приложения) и записывает по этому адресу адрес инструкции следующей за инструкциейcall
, после чего перемещает поток по адресу который был передан.call eax //Перемещает поток на адрес находящийся в eax
ret
- Берёт значение адреса (или любое) находящееся по адресу стека и перемещает на него поток, после чего добавляет к адресу стека 4, или 8.
Если у инструкции есть аргумент в виде числа, тогда дополнительно сдвигает стек после переноса потока по адресу.
Например, по стандарту ret должен был сдвинуть 4 байта, но это была инструкцияret 8
и в итоге ret сдвинет стек (добавит к адресу стека в esp) на 12 байт.ret //Простой ret 8 //С дополнительным сдвигом
Пример функции "fo" без аргументов которая всегда возвращает значение 16:
fo: mov eax,5 mov ecx,#11 add ecx,eax mov eax,ecx ret
Пример "fo2" функции с аргументами, которая принимает через стек 2 аргумента и складывает их, после чего возвращает значение результата через регистр eax и убирает из стека помещённые значения:
//После вызова с помощью call в [esp] находится адрес куда вернуться потоку, в [esp+4] и [esp+8] находятся аргументы. fo2: mov eax,[esp+4] add eax,[esp+8] ret 8
Пример вызова функции "fo2" с аргументами:
push 9 //Загрузка первого аргумента push 7 //Загрузка второго аргумента call fo2 // Теперь в eax находится число 16
Подробнее про вызов функций рассказано в следующих статьях
-
Принцип создания свободной камеры в играх
Создание свободной камеры для одиночной игры на примере игры War Thunder
Свободная камера, подразумевает возможность полёта камеры отдельно от объекта/персонажа и тому подобного, используется в самых разных целях, для обнаружения противников, для создания красивых снимков, для нахождения секретов и прочего.
Принцип создания:
Всё зависит от типа игры. Если реализован поворот камеры мышью - то данную функцию делать не нужно. Для перемещения камеры можно использовать самые разные функции, но я склоняюсь к полёту в ту сторону куда смотрит игрок. Для этого необходимо вычислить синус и косинус для поворота по горизонтальной, и синус для поворота по вертикальной оси. После их надо умножить на радиус, мы получим точку на сфере - это и будет вектор ускорения для камеры. Его следует добавлять к уже существующим координатам камеры, изменяя радиус мы можем изменять скорость.
Для того что бы камера была "свободная", нужно записывать свои значения в координаты, а функцию которая записывает их в игре по стандарту - отключить.Более детально всё показано в следующем видео:
Видео с демонстрацией работы разных формул:
Видео от другого участника форума на примере игры Dark Souls:
Imaginary
-
Взлом мобильных приложений с помощью CE server
Cheat Engine сервер:
Предназначен для удалённого взлома каких либо приложений, сервер располагается на целевом устройстве, а клиент подключается к нему по IP, после этого становятся доступны почти все функции стандартного Cheat Engine.
Установка Cheat Engine сервера на Android:
Для установки и использования вам потребуются:
- root права в системе.
- Приложение - терминал, скачать можно например из Google play.
- Сам сервер, который можно скачать с официального сайта, в разделе Download снизу, под вашу версию Android.
После того, как у вас есть все эти компоненты, можно приступать к установке.
Сначала, вам нужно найти системную папку с файлом sh, у меня это /system/bin:После, нужно распаковать файлы из скачанного архива сервера в эту папку (файлы могут называться иначе):
После распаковки, останется только запустить сервер. Сделать это можно с помощью приложения терминал.
Команды:su --Дать терминалу права суперпользователя. system/bin/ceserver_x86 --Путь к файлу сервера. (какой у вас файл, и путь, вводите свой)
При успешном запуске, вы увидите сообщение от сервера, в котором он пишет что ожидает подключения клиента:
Что бы подключиться к серверу, вам нужно открыть клиент CE, и ввести ip адрес сервера, и порт (стандартный 52736), не забывайте что для подключения вне локальной сети порт должен быть открыт.
После подключения вы увидите список процессов на устройстве, и сможете взаимодействовать с ними:
Cheat Engine сервер может иметь проблемы с выделением памяти и прочим, поэтому, если у вас не работает выделение памяти, используйте уже существующие участки памяти, например неиспользуемые функции в библиотеках:
[ENABLE] aobscan(PlayerL, 8B 9B A4 04 00 00) //Поиск инструкции по сигнатуре registersymbol(PlayerL) libopus.haar1: //Код в выбранном месте, неиспользуемая функция библиотеки mov [ebx+000004A4],#500 //Установить 500 здоровья originalcode: mov ebx,[ebx+000004A4] //Оригинальная инструкция jmp returnhere //Возврат в код после прыжка PlayerL: jmp libopus.haar1 //Прыжок на новый код nop returnhere: [DISABLE] PlayerL: db 8B 9B A4 04 00 00 //Восстановление оригинальной инструкции unregistersymbol(PlayerL)
Imaginary