Skip to content

Auto Assembler Basics: Understanding AOB Injection Scripts in Cheat Engine

Cheat-Engine.net By Cheat-Engine.net 8 min read 33 views

What a script entry is, how [ENABLE] and [DISABLE] work, and a line-by-line walk through Cheat Engine's AOB injection template: aobscanmodule, alloc, labels, symbols and wildcards.

Most of the useful entries in shared cheat tables are not plain values but scripts: infinite health, no reload, free crafting. They are written in Cheat Engine's Auto Assembler, a small scripting format that combines x86 assembly with commands for finding and patching code. This guide explains what such a script does, walks through the AOB injection template that Cheat Engine generates for you, and covers the rules that make a script reliable.

You will get more out of it if you already know how to find a value and what a pointer is; the pointer scanning guide covers that background. Scripts change a running game's code, so use them only in single-player and offline games, save before you test, and keep backups of your save files.

What a script entry is

A script entry is an item in the address list whose Value column shows <script>. Instead of pointing to a value, it contains Auto Assembler code. Ticking the entry's Active box runs the script's [ENABLE] section; unticking it runs the [DISABLE] section. The guide on how to use a cheat table covers this from the user's side.

The typical script does not change a value once. It changes the game's own instruction that writes the value, so the effect is permanent while the script is active. For example, the instruction that stores your new health after damage can be redirected to code that stores the maximum instead.

Scripts have a big advantage over plain addresses: they locate their target by searching for a pattern of bytes in the game's code, so they work across restarts without any pointer. The cost is that they depend on that code staying the same, which ties them to a game version.

[ENABLE] and [DISABLE]

Every toggleable script has both sections. [ENABLE] finds the code, allocates memory for new code, and writes a jump from the game's instruction to the new code. [DISABLE] undoes all of it: it writes the original bytes back, removes the names it registered, and frees the memory. A well-written [DISABLE] leaves the game exactly as it was. If it is missing or wrong, unticking the entry leaves the game in a patched or broken state until you restart it.

Finding the instruction and generating the template

  1. Find the value you want to control and add it to the address list.
  2. Right-click it and choose Find out what writes to this address. Make the value change in the game. One or more instructions appear in the list.
  3. Select the instruction and open it in the disassembler (Memory Viewer).
  4. With that instruction selected in the Memory Viewer, open Tools → Auto Assemble.
  5. In the Auto Assemble window, choose Template → AOB Injection. Confirm the address and accept or change the symbol name, which defaults to INJECT.
  6. Edit the script, then use the window's File menu to assign it to the current cheat table. It appears in the address list as a new script entry.

The AOB injection template, line by line

Below is an example of the structure the template produces. The process name, symbol and bytes are made up for illustration; this is not code for any real game.

{ 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,...) searches the memory of the module game.exe for the byte pattern and, if found, defines the name INJECT as the address where it starts. Limiting the search to one module is faster and avoids false matches elsewhere. Related commands exist: aobscan searches all memory, and aobscanregion searches between two addresses. If the pattern is not found, the script fails to enable with an error, which is the usual symptom after a game update.

alloc

alloc(newmem,$1000,INJECT) reserves 0x1000 bytes of memory for your code and calls it newmem. The third parameter asks Cheat Engine to allocate it close to INJECT. In 64-bit games this matters: a short 5-byte jmp can only reach about 2 GB in either direction, and allocating nearby keeps the jump small enough to fit in place of the original instruction.

label

label(code) and label(return) declare names for positions that are defined further down. code marks where the original instruction is replayed; return marks the instruction right after the patched one, where execution continues.

newmem and code

Everything under newmem: is your code, followed by the original instruction under code:. In the example, mov eax,#999 sets the register to 999 (the # marks a decimal number), and the original mov [rbx+000000F0],eax then stores it, so the value is always written as 999. Finally jmp return goes back into the game's code.

INJECT: jmp newmem

At the found address, the script overwrites the original instruction with jmp newmem. The jump takes 5 bytes but the original instruction here was 6 bytes, so a nop fills the leftover byte; otherwise the processor would try to run half an instruction. The template counts this for you. return: is placed right after, so it marks the next untouched instruction.

registersymbol and unregistersymbol

registersymbol(INJECT) makes the name INJECT known globally in Cheat Engine. That is what allows the [DISABLE] section, which runs later and separately, to find the same address without scanning again. It also lets other entries refer to it. unregistersymbol(INJECT) in [DISABLE] removes the name.

Restoring original bytes, and dealloc

In [DISABLE], INJECT: followed by db 89 83 F0 00 00 00 writes the original bytes back over the jump, which restores the game's instruction exactly. Then dealloc(newmem) frees the memory that held your code. The order matters: restore the jump first, so the game is no longer using newmem when it is freed.

Wildcards and why unique signatures matter

The byte pattern in aobscanmodule is called a signature. It has to meet two conditions:

  • It must be unique. If the pattern occurs more than once, the script patches the first match, which may be a completely different function. That is how scripts crash games or change the wrong thing. The template adds the comment "should be unique" as a reminder.
  • It should survive small changes. Some bytes change easily between game versions or even between runs: offsets inside instructions, relative addresses of calls and jumps, and embedded constants. Replacing those bytes with ?? wildcards lets the pattern keep matching when only those details change.

These two goals pull against each other. Too few bytes and the pattern matches in many places; too many wildcards and it becomes generic again. A practical approach is to keep the opcode bytes, wildcard the volatile offsets and addresses, and include a few bytes of the following instructions for context. Then check that the pattern is unique: in the main window, set Value Type to Array of byte, paste the pattern and scan with the memory options set to include executable memory. Exactly one result is what you want. The AOB signature maker helps you turn copied bytes into a wildcard pattern and spot which bytes are likely to change.

Testing a script

  • Save the game and keep a backup of your save before the first test.
  • Enable the script, check the effect, then disable it and confirm the game behaves normally again.
  • Toggle it several times. A script that fails on the second enable usually has a [DISABLE] section that does not fully undo [ENABLE].
  • Be careful with shared instructions. The instruction that writes your health may also write enemy health; in that case your change affects everyone, and you will need to tell the cases apart before changing anything.

Once a script works, give the entry a clear description and save the table. When the game updates and the script fails to enable, the signature is the first thing to check.

Comments

0
Replying to

Never shown publicly.

Comments are reviewed by a moderator before they appear.

No comments yet

Be the first to share your thoughts.