Основы Auto Assembler: как работают скрипты AOB-инъекции в Cheat Engine
Что такое запись-скрипт, как работают [ENABLE] и [DISABLE], и построчный разбор шаблона AOB-инъекции Cheat Engine: aobscanmodule, alloc, метки, символы и маски.
Большинство полезных записей в общих таблицах Cheat Engine (Cheat Table) — это не простые значения, а скрипты: бесконечное здоровье, отсутствие перезарядки, бесплатный крафт. Они пишутся на Auto Assembler из Cheat Engine — небольшом скриптовом формате, который сочетает ассемблер x86 с командами для поиска и патча кода. В этом руководстве объясняется, что делает такой скрипт, разбирается шаблон AOB-инъекции, который Cheat Engine создаёт для вас, и описаны правила, делающие скрипт надёжным.
Вы получите больше пользы, если уже умеете искать значение и знаете, что такое указатель; эту базу описывает руководство по поиску указателей. Скрипты изменяют код запущенной игры, поэтому используйте их только в одиночных и офлайн-играх, сохраняйтесь перед проверкой и делайте резервные копии файлов сохранений.
Что такое запись-скрипт
Запись-скрипт — это элемент списка адресов, в столбце «Значение» которого отображается <script>. Вместо указания на значение она содержит код Auto Assembler. Если поставить галочку в поле Active у записи, выполнится секция скрипта [ENABLE]; если снять — секция [DISABLE]. Руководство о том, как пользоваться таблицей Cheat Engine (Cheat Table), рассматривает это со стороны пользователя.
Обычный скрипт не меняет значение один раз. Он меняет собственную инструкцию игры, которая записывает это значение, поэтому эффект сохраняется, пока скрипт активен. Например, инструкцию, сохраняющую ваше здоровье после урона, можно перенаправить на код, который сохраняет максимум.
У скриптов есть большое преимущество перед обычными адресами: они находят цель, ища шаблон байтов в коде игры, поэтому работают после перезапусков без всяких указателей. Цена этого в том, что они зависят от неизменности кода, а значит привязаны к версии игры.
[ENABLE] и [DISABLE]
У каждого переключаемого скрипта есть обе секции. [ENABLE] находит код, выделяет память под новый код и записывает переход от инструкции игры к новому коду. [DISABLE] отменяет всё это: записывает обратно исходные байты, удаляет зарегистрированные имена и освобождает память. Хорошо написанная секция [DISABLE] оставляет игру точно такой, какой она была. Если её нет или она написана неверно, снятие галочки оставит игру в изменённом или сломанном состоянии до перезапуска.
Поиск инструкции и создание шаблона
- Найдите значение, которым хотите управлять, и добавьте его в список адресов.
- Щёлкните по нему правой кнопкой мыши и выберите Find out what writes to this address. Измените значение в игре. В списке появятся одна или несколько инструкций.
- Выберите инструкцию и откройте её в дизассемблере (Memory Viewer).
- Выделив эту инструкцию в Memory Viewer, откройте Tools → Auto Assemble.
- В окне Auto Assemble выберите Template → AOB Injection. Подтвердите адрес и примите или измените имя символа, по умолчанию это
INJECT. - Отредактируйте скрипт, затем через меню File окна назначьте его текущей таблице Cheat Engine (Cheat Table). Он появится в списке адресов как новая запись-скрипт.
Шаблон AOB-инъекции построчно
Ниже приведён пример структуры, которую создаёт шаблон. Имя процесса, символ и байты придуманы для иллюстрации; это не код какой-либо реальной игры.
{ EXAMPLE STRUCTURE ONLY - not code for a real game.
Process: game.exe Symbol: INJECT Bytes: made up }
[ENABLE]
aobscanmodule(INJECT,game.exe,89 83 F0 00 00 00 48 8B 5C 24 ??) // should be unique
alloc(newmem,$1000,INJECT)
label(code)
label(return)
newmem:
mov eax,#999 // your change: store 999 instead
code:
mov [rbx+000000F0],eax // the original instruction
jmp return
INJECT:
jmp newmem
nop
return:
registersymbol(INJECT)
[DISABLE]
INJECT:
db 89 83 F0 00 00 00 // original bytes: mov [rbx+000000F0],eax
unregistersymbol(INJECT)
dealloc(newmem)
aobscanmodule
aobscanmodule(INJECT,game.exe,...) ищет в памяти модуля game.exe шаблон байтов и, если находит, определяет имя INJECT как адрес его начала. Ограничение поиска одним модулем ускоряет его и исключает ложные совпадения в других местах. Есть и родственные команды: aobscan ищет по всей памяти, а aobscanregion — между двумя адресами. Если шаблон не найден, скрипт не включается и выдаёт ошибку — это обычный признак после обновления игры.
alloc
alloc(newmem,$1000,INJECT) резервирует 0x1000 байт памяти под ваш код и называет эту область newmem. Третий параметр просит Cheat Engine выделить её рядом с INJECT. В 64-битных играх это важно: короткий 5-байтовый jmp достаёт лишь примерно на 2 ГБ в любую сторону, а выделение рядом позволяет переходу поместиться на место исходной инструкции.
label
label(code) и label(return) объявляют имена для позиций, которые определяются ниже. code отмечает место, где повторяется исходная инструкция; return отмечает инструкцию сразу после изменённой, откуда продолжается выполнение.
newmem и code
Всё под newmem: — это ваш код, за которым следует исходная инструкция под code:. В примере mov eax,#999 записывает в регистр 999 (символ # обозначает десятичное число), а исходная mov [rbx+000000F0],eax затем сохраняет его, поэтому значение всегда записывается как 999. Наконец, jmp return возвращает выполнение в код игры.
INJECT: jmp newmem
По найденному адресу скрипт перезаписывает исходную инструкцию на jmp newmem. Переход занимает 5 байт, а исходная инструкция здесь была 6 байт, поэтому nop заполняет оставшийся байт; иначе процессор попытался бы выполнить половину инструкции. Шаблон считает это за вас. return: стоит сразу после, поэтому отмечает следующую нетронутую инструкцию.
registersymbol и unregistersymbol
registersymbol(INJECT) делает имя INJECT известным глобально в Cheat Engine. Именно это позволяет секции [DISABLE], которая выполняется позже и отдельно, найти тот же адрес без повторного сканирования. Также на него могут ссылаться другие записи. unregistersymbol(INJECT) в [DISABLE] удаляет это имя.
Восстановление исходных байтов и dealloc
В [DISABLE] строка INJECT: с последующей db 89 83 F0 00 00 00 записывает исходные байты поверх перехода, что в точности восстанавливает инструкцию игры. Затем dealloc(newmem) освобождает память, где хранился ваш код. Порядок важен: сначала восстановите переход, чтобы игра уже не использовала newmem, когда она освобождается.
Маски и почему важны уникальные сигнатуры
Шаблон байтов в aobscanmodule называется сигнатурой. Она должна отвечать двум условиям:
- Она должна быть уникальной. Если шаблон встречается более одного раза, скрипт изменит первое совпадение, которое может оказаться совсем другой функцией. Так скрипты роняют игры или меняют не то. Шаблон добавляет комментарий «should be unique» как напоминание.
- Она должна переживать небольшие изменения. Некоторые байты легко меняются между версиями игры или даже между запусками: смещения внутри инструкций, относительные адреса вызовов и переходов, встроенные константы. Замена этих байтов масками
??позволяет шаблону продолжать совпадать, когда меняются только эти детали.
Эти две цели противоречат друг другу. Слишком мало байтов — и шаблон совпадает во многих местах; слишком много масок — и он снова становится общим. Практичный подход: оставить байты опкодов, заменить масками изменчивые смещения и адреса и добавить несколько байтов следующих инструкций для контекста. Затем проверьте уникальность шаблона: в главном окне установите Value Type в Array of byte, вставьте шаблон и выполните поиск, включив в параметры памяти исполняемую память. Вам нужен ровно один результат. Генератор AOB-сигнатур поможет превратить скопированные байты в шаблон с масками и понять, какие байты, вероятно, изменятся.
Проверка скрипта
- Сохраните игру и сделайте резервную копию сохранения перед первой проверкой.
- Включите скрипт, проверьте эффект, затем отключите его и убедитесь, что игра снова ведёт себя нормально.
- Переключите его несколько раз. Если скрипт даёт сбой при втором включении, то обычно секция
[DISABLE]не полностью отменяет[ENABLE]. - Будьте осторожны с общими инструкциями. Инструкция, записывающая ваше здоровье, может записывать и здоровье врагов; в таком случае ваше изменение коснётся всех, и перед любыми правками нужно будет различить эти случаи.
Когда скрипт заработает, дайте записи понятное описание и сохраните таблицу. Если игра обновилась и скрипт не включается, первым делом проверьте сигнатуру.
Комментарии
Комментариев пока нет
Будьте первым, кто поделится своим мнением.