- Intro
- History
- Static Addresses
- Pointers
- ASM/Code Edits
- Making ASM/Code Edits
- Using Scripts
- AOBs (Making It Last).
- A Good Signature
- AOB Injection Template
- Handling FSTP
1. Intro
So if you’re here, it’s likely because you’ve been trying out new cheat tables for new games, and
instead of addresses and pointers you see scripts everywhere. You check these scripts, think
“WTF do these ancient runes mean”, but marvel at the black magic they hold (or some crap like that).
I’m going to teach you what these scripts do, why they’re used so often nowadays, and how to make
them yourself. First, I think that a brief history of the stages/techniques used in game hacking
is in order so you know why we do this the way we do.
This tutorial assumes that you have at least a basic understanding of cheat engine.
If you don’t know how to find and edit stuff in games at all yet, go somewhere else first.
2.a Static Addresses
The first and most basic type of game hacking most people are familiar with is static RAM editing.
You find an address and whatever tool you’re using keeps resetting it to a certain value very quickly
to “lock” it there. The Gameshark for the Gameboy and the Action Replay for the SNES worked like this.
These codes were generally short and simple. For example the code to always have the cape in
Super Mario World for the SNES is 7E001902.
We can break this down into…
- 7E: Bank of memory to work on. 7E is the RAM bank.
- 0019: The memory address to edit. This is the SNES so there’s not that many possible addresses in RAM!
- 02: The value to set it to (in this case the cape).
The basic idea of just having a single address to edit every time applies on the PC too, but is usually only
useful in very old and/or custom-engine games. Cave Story and Nethack, for example, are PC games that
still use static addresses for the player data. The main downside to this is that if a game doesn’t
load it’s data into the exact same places each run, then you’ll have to rescan every time you play.
2.b Pointers
As systems and games got more complex, they stopped holding the same things in the exact same memory
addresses every single time in order to account for varying numbers of players and entities and monsters
and rules in effect. Since the memory locations were shifting around, pointers are used to keep track
of what exists where. This is what most people will be familiar with as more advanced cheating, because
you can use certain methods/tools to find out the pointer paths and then lock/change the final address.
But even though pointers tend to work after a game has been restarted multiple times, this shares a
downside with just locking the address manually (since that’s all that’s being done). On the PC, tools
like Cheat Engine can’t really “lock” an address. What they do is inject/overwrite it with your chosen
value multiple times a second. In many cases this is enough, but if, for example, your character only
has 100 max HP and you take an attack of 115 damage… in most cases you still die. This is because
the game’s logic is running much faster than CE can reset the value, so the game realizes that you
died in that split second. Obviously something other than RAM locking is needed to get around this.
2.c ASM/Code Edits
So, given the above example, how would somebody stop dying if they’re dealt more damage than they have
health? The code that deals damage in the first place should be edited. This was the idea behind
the old Game Genie devices for the NES, SNES, and such. They edited the ROM reads instead of RAM,
to change some data around to make the game run differently. After all, you don’t need to keep
finding and locking your money amount if you edit the game’s code so that your money is never
taken away when you buy something!
“But Rydian, if this is so much more powerful, why did all the Game Genie codes suck ass? If they could make
us invincible or anything they wanted why did they keep making each apple picked up worth 5 apples instead?”
This boils down to two big flaws in the original Game Genie’s idea and implementation.
- Without any way to debug/trace what games were doing, making your own codes as a customer is a
shot in the dark. Edit random bytes and see what happens, keep the few positive things as codes,
discard all the crashy/negative things. - The Game Genie’s codes were encrypted, and it wasn’t until a few years later that people would
publicly make converters to allow you to tell the Game Genie to edit arbitrary ROM reads.
These two things combined made it so that the only good/targeted codes were from Galoob itself
(or whoever was doing the distribution of the device at the time). Thankfully that’s not the case with
the PC. There’s all sorts of debugging, tracing, and logging tools available, in fact Cheat Engine
actually has it’s own debugger and tons of other tools (that are hidden by default) that are
specifically geared towards making cheats.
3. Making ASM/Code Edits
For this example I’m going to be using the original version of Cave Story for the PC (which is freeware,
not to be confused with Cave Story+ or the Wii/3DS releases).
Download it here, and there’s a link to the translation patch too.
The first thing you’ll want to do is to start a new game, and get used to the awkward-as-hell controls.
Then you want to launch+attach Cheat Engine and do the usual bit with scanning for the RAM, in this
case we want to find health. Change it to make sure you found the right value.
Next you want to right-click that table entry, and choose “Find What Writes To This Address”.
That will bring up a new window that logs any bits of code that change that address. Go back to the
game and get hit or something a few times and you’ll see one or more entries show up in the list.
Once you see a few things show up, hit the “stop” button so the logging stops. Click the entry that
comes up when you get hit (each different type of effect on the health will usually have it’s own
entry and they’re numbered by how often they happened), then click that “Show Disassembler” button
on the right to open up the Memory Viewer window, which is where the magic is. This is a big window,
but right now we’re only concerned with the top half of it. Scroll up a bit so the targeted line
is more or less centered.
What we see right there is the actual assembly that makes up the running game. It doesn’t matter
which language a game is written in or which engine it runs on. Anything that runs is assembly
one way or the other. For example you don’t run C++ code itself, you put C++ code through the
compiler, which turns it into assembly (more or less). Even interpreted languages like Javascript
get turned into assembly when they run. So if you can edit assembly in RAM, then you can edit any
program’s behavior, no matter what language it was written in.
At this point, I suggest you go look at some basic x86 assembly tutorials, or at least a newbie
instruction list, but I will run over some of the very basics you need to know in this instance.
That “mov” instruction that’s highlighted is what takes the new calculated health amount and sets
our health address to it. If you look at the bottom of the assembly view, you’ll see “copy memory”,
which describes the “mov” command. Any time you have an operation/line highlighted, that little
box will show you what it stands for.
The syntax is generally (operation) (destination),(source). So for the mov command, it’s moving
whatever’s in register cx (part of ecx) into memory address 0049E6CC. Sort of like
$currenthealth = $calculatedhealth; in a more modern language.
And the command above that is a subtraction.
You’ll also see things like “eax” and “ecx” everywhere. These are the x86 registers. You can,
for this type of work, think of a register as the simplest form of a variable there is. It’s
actually physical memory housed inside the CPU itself.
So in this case we can see that there’s math done to determine the damage, then the game moves
the new health into the current health. So if we want to stop taking damage, we can edit either
of these. If we remove the subtraction, your health is never lowered. If we remove the mov right
after it, then even though the game determines what your new health should be, it never
becomes that value. In this case we’ll focus on the subtraction.
The simplest kind of edit we can do is to make one of the operations simply not happen. To do this,
we generally replace the bytes that make up that operation with the bytes that stand for “do nothing”.
In x86 the “no operation” (nop or noop) byte is 90 (in hex). Cheat Engine, being geared for game
cheating, actually has a quick function to do that, which we’ll use just for example.
Right-click the “sub” line (right above the targeted mov line) and choose “Replace With Code That
Does Nothing”. Hit enter for the default on the prompt, and you should see the change.
And when you go back into the game, you shouldn’t take any damage from enemies anymore. You can have
3 max HP and take 5 damage from the spikes in the starting area, and nothing happens. Yay!
But that was just a quick example to show you the context. You’ll rarely be doing that normally,
except for testing. So in the Memory Viewer window again, right-click the edited code and choose
“Restore with original code”, because we’re going to do something else.
4. Using Scripts
So instead of right-clicking that “sub” line and using a built-in function to remove it, we want to write
a script that focuses on that section of code. Highlight the “sub” command and his CTRL+A (or go to
Tools – Auto Assemble). In the new window that comes up, go to Template – Cheat Table Framework Code and
then Template – Code Injection (and hit okay on the default).
This should make Cheat Engine fill in the Auto Assembly window with something that looks like this,
which is the basic framework you need to customize the game’s code. I’ve marked out, in a basic sense,
which each segment does.
So you can see, for this example, the “originalcode” section is what we want to edit. It put in the
original code for us automatically, but we can do whatever we want. For now though, what you want to
do is hit File – Assign To Current Cheat Table, then close the existing window. This is important,
do NOT hit the “execute” button. Assign it to the cheat table, then re-open it from there, and the
“execute” button will be replaced with “ok” (which just saves the script).
Now that the script is saved on the cheat table and we can edit it on and off (by toggling/locking it
like a normal cheat), feel free to replace or modify the original code. For example change the “sub”
into an “add”, or simply comment it out (//thisisacomment), and when you enable the script Cheat Engine
will interpret what you typed (assuming no syntax errors) and make whatever edits you intend for it to.
The way this works is that Cheat Engine will overwrite the original code with a jump to some new code,
and then include whatever code you want, which then jumps back at the end. This means that you can
insert new code as well, so if you wanted to change the math or logic being done, you generally have
enough room to write a small little assembly routine there to do whatever, so have fun with it.
5. AOBs (Making It Last)
Note: this section assumes that you’ve messed around with assembly editing in Cheat Engine enough
to have a basic grasp of the concept and know what you’re doing.
So making a script that edits the game code is a great way to get around moving memory addresses.
You don’t need to scan for pointers or watch changing addresses when you edit the game code to control
things. But… newer games (especially ones written in .NET and such) don’t even load their code in
the same order each time! So we need a way to find where certain code snippets are, and then
reference/edit them. We do this with AOBscans. AOB stands for “Array of Bytes”, and is just a list of
values in RAM.
You write a script in the Auto Assembler window (CTRL+A in the memory browser, add it to the table
like before and edit it from there), and here’s a very basic AOB script for editing some assembly.
Code: |
[ENABLE] aobscan(nodamage, 2B C8 66 89 0D CC E6 49 00 8B 15 50 E6 49 00 81 E2 80 00 00 00 74 1C) label(_nodamage) registersymbol(_nodamage) nodamage: [DISABLE] unregistersymbol(_nodamage) |
In this specific case, it’s a “No Damage” code for Cave Story. The first thing it does is scan for
certain bytes in RAM in a certain order (using aobscan to find a unique sequence of bytes, known here
as a signature). Then it applies a label (_nodamage) to that found address (sort of like a variable).
Then it acts on that address. In this case I’m using the “db” command, which writes specific bytes.
In the “enable” section it’s writing the bytes “90 90”, which is nop, remember? Then the disable
section writes the original bytes back (2B C8, which was the sub).
Instead of using “db”, you could just write out your assembly normally, but with this kind of simple
replacement you can’t add more code than was already there, you’re only limited to the number of bytes
that already exist, so I usually just use db to keep it simple and remind myself of the limits.
“But wait, what the hell are the bytes at the beginning of the scripts?”
Well… it’s the snippet of code we want to find/target.
If you start with the line of code that you want to edit and then select it and a few more instructions
after it, you can right-click and Copy To Clipboard – Bytes Only (No Addresses). This will copy the
string of bytes for you to paste right into the template (and make sure to change the [DISABLE] section
to put the right new bytes back too).
So there’s a basic and direct AOB assembly replacement script for making minor changes.
It’s very important to remember that when you’re manually overwriting bytes like this (without
injection) that the replacement and disable bytes need to account for eachother.
For example this below code handles it properly…
Code: |
_nodamage: db 90 90 [DISABLE] |
However this below code it just asking for crashes…
Code: |
_nodamage: db 90 90 90 90 [DISABLE] |
That’s because it’s not fixing all of the edited bytes, it’s not putting things back the way they were. It’s
also the reason that stuff is overwritten with 90 (nop, no operation), to keep the same number of bytes
modified. For inserting more code, you’ll want to use either the code injection (step 3) or AOB injection
(step 7) template, in which CE allocates your own little code space and shuffles things around for you.
6. A Good Signature
So let’s say you’ve made some aobscans for various games. Some of them work just fine, but others stop
enabling after a restart of the game or something. This just means that you need to find better
signatures (the sequence of bytes to search for). The two main things you can do to improve your
signatures is to use wildcards to avoid changing addresses/offsets, and to shift your signature up or
down more and then refer to it with an offset in order to target a more unique string of data.
For the wildcards, let’s take our Cave Story example aobscan and look at it closer.
The bytes I’ve circled in red are the kinds of things you usually don’t want to reference directly.
They’re memory addresses that may change from one run to another. (This isn’t the case with Cave Story
specifically, but tons of games do this). So in order to avoid referencing that data directly, we’ll
just use wildcards. We replace the digits that can change with a question joe.
So…
Code: |
2B C8 66 89 0D CC E6 49 00 8B 15 50 E6 49 00 81 E2 80 00 00 00 74 1C |
Becomes
Code: |
2B C8 66 89 0D ?? ?? ?? ?? 8B 15 ?? ?? ?? ?? 81 E2 80 00 00 00 74 1C |
Generally anything that’s a small offset (like +2 or +216) isn’t going to change, it’s the huge things
(four bytes or so) that do change and should be replaced with wildcards. But beware, the more wildcards
you have, the less unique your signature is, so you may need to add more bytes to search for at the
end if you have a lot of wildcards.
Sometimes you may not be able to find a good signature directly after the code you want to edit. Sometimes
you have the line you want to edit, followed by 4-6 functions that deal with random addresses and numbers
that keep changing. That’s okay, you can search ahead of the function you want to work off of too!
So here’s the same code, but using both techniques.
7. AOB Injection Template
Now that you know the basics of how to edit game code and what an AOB and such is, you can take a much
shorter method to get custom scripts up and running. Make sure that your version of Cheat Engine is at least
6.4, that’s when this feature was included. When you target some code and open up the AA window, this time
go to Template – Cheat Table Framework and then Template – AOB Injection.
It’ll ask which address you want the jump on, defaulting to what was highlighted when you opened the AA
window, and this is usually what you want anyways.
Next it’ll ask you to name the symbol. Make sure you give it an actual unique name for the table.
Next CE make take a few moments because it’ll try to develop and AOB scan that’s unique to the code you
targeted, but once it’s done it’ll present you with a nice AOB injection template.
As before, the orange box indicates the copy of the original game code that will be injected for you to change.
8. Handling FSTP
Once you go off to start making your own things for games, you’ll likely run into situations where games use
floats (floating-point numbers) for things. In theory you could use the same sort of techniques here, but the
thing is that a lot of the time the instruction that writes the final value to memory is FSTP. This stands for
FloatingpointSToreandPop (more or less). This unfortunately means that not only does
the instruction modify the target value, but it also modifies the stack. Stack modification is very important
to keep track of, because an unbalanced stack can cause all sorts of problems or outright crashes in games.
This basically means that the safest thing to do when you’re dealing with floating-point instructions is to avoid
removing them. Unless you’re quite familiar with assembly and the stack and such, what you’ll want to do is
overwrite the results instead. For example let’s say that this is our target function here, an fstp.
Since we need to insert our own code to handle this type of thing, you’ll want to use the AOB injection
template like you were shown earlier in this guide. Once you do that, look at the code section as usual…
Now, in order to overwrite the results of the FSTP into the target address, we’ll simply add our own instruction
there which will set it to the value we specifically want. The easiest way to do this is with a mov.
And with that, the code shouldn’t cause odd problems or crash the game anymore.