Code Caves, Utilizing – Game Hacking(JMP Method)

Code caves are areas of memory that are unused by a process.  These areas come in handy when editing process execution because when editing a game’s code-flow at run-time, we are limited by the amount of space allocated for the original opcodes.  In most instances, if we modify an area of memory containing a 3 byte instruction with a 5 byte opcode, we unintentionally overwrite 2 bytes of the next instruction in the routine.  Needless to say that this can lead to issues if we overwrite something important and at the very least it will lead to the program not behaving as intended originally.

In order to avoid this issue, we can use code caves.  A code cave is simply a place in the game’s memory layout that is either full of instructions that don’t do anything important, or is simply empty.   The technique is rather simple:

    1. We find an empty space(or code cave) in the game’s memory.
    2. We overwrite an instruction in the original code to jump to that empty area.
    3. We fill the code cave with our code.
    4. We jump back to where we left off in the original code.

[Tools Needed]

If you want to be able to follow this example step by step you should have the following:

  1. Cheat Engine
  2. Planescape Torment

I have the original boxed edition of Planescape, so my offsets and codecave addresses may be different from yours if you are using the GOG version.  Everything else should remain the same though.

[Example-Making the Nameless One receive 4000 xp per kill no matter what we kill]

Note: I have skipped the step of finding the function where XP is allocated here.  If you do not know how to do it I recommend you google how to do it.  For this example I just memory searched for the XP address, then selected “show what writes to this address” in CE.

The first thing we do is take a look at the function that modifies the XP of the Nameless One when we kill things.

code caves

In this function the total XP ends up in edx.  The address where the XP is stored is in eax, which was pulled from the stack at ebp-28.   I would like to add 4000 dec to my xp total on every kill, however, the opcode adding the XP value into edx is 2 bytes. (add edx, eax).  And the opcode for add eax, 1000 is 5 bytes.  This means that if I overwrote “add eax, edx” with “add eax, 1000” I will be eating up the instruction right below it(which pulls the address of XP from the stack and loads it into eax).   Since that’s not a possibility, we will have to find somewhere else to put in our code.

We do this by searching for empty or useless sections of code within the game.  CE has a tool for that, and so we use it.

code caves code cavesWe check out the first code cave returned which is at 00400019.

code caves

It looks like 12 decent bytes of space for us to write in.  And so we go back to the function in charge of setting the XP on kill.  We will overwrite the instructions at C55E2(2 bytes) and C55E4(3 bytes) with a jmp to our codecave at offset+19(5 bytes).  This will cause the code-flow to be redirected to our codecave every time we get XP for something.

code caves

And now we write our code in the codecave to add 4000 to our XP whenever we kill something and return the flow of execution to the function in charge of XP.   Because we replaced 2 instructions of the original code, we put them back inside our codecave so that the function remains exactly like it was before(with the exception of our XP addition).  And we add a jump to return back to the XP function.

code caves

[Conclusion]

Code caves allow you to add snippets of code to a game in order to modify the game’s behavior.  By utilizing code caves, you can modify the game without worrying about byte constraints of the instruction layout.

3 Responses to Code Caves, Utilizing – Game Hacking(JMP Method)

  1. Samedi Ishmael Medivh says:

    This is an amazing intro to code caves! 🙂 Thanks!:)

  2. Alisson says:

    Thanks for sharing this amazing tutorial.

  3. bombo says:

    thanks man

Leave a Reply

Your email address will not be published. Required fields are marked *