14

Lets assume I am a game and I have a global int* that contains my health. A game trainer's job is to modify this value to whatever in order to achieve god mode. I've looked up tutorials on game trainers to understand how they work, and the general idea is to use a memory scanner to try and find the address of a certain value. Then modify this address by injecting a dll or whatever.

But I made a simple program with a global int* and its address changes every time I run the app, so I don't get how game trainers can hard code these addresses? Or is my example wrong?

What am I missing?

AstroCB
  • 12,337
  • 20
  • 57
  • 73
GameTrainersWTF
  • 235
  • 1
  • 2
  • 6
  • You need to find the area by finding it. So, locate things it is near. Find little hints that you are coming 'near' the area you want. I.e. the job is now to determine the layout of memory, what is held there, and what you are after specifically (and how it looks). – Noon Silk May 28 '10 at 05:09
  • Interesting, this would be cool to know. Though my guess would have been that there are OS memory protection features in place to protect programs accessing memory that is not their own.. Though trainers must get around that somehow! – filip-fku May 28 '10 at 05:10

5 Answers5

7

The way this is usually done is by tracing the pointer chain from a static variable up to the heap address containing the variable in question. For example:

struct CharacterStats
{
    int health;
    // ...
}

class Character
{
public:
    CharacterStats* stats;

    // ...

    void hit(int damage)
    {
        stats->health -= damage;
        if (stats->health <= 0)
            die();
    }
}


class Game
{
public:
    Character* main_character;
    vector<Character*> enemies;
    // ...
}

Game* game;

void main()
{
    game = new Game();
    game->main_character = new Character();
    game->main_character->stats = new CharacterStats;

    // ...

}

In this case, if you follow mikek3332002's advice and set a breakpoint inside the Character::hit() function and nop out the subtraction, it would cause all characters, including enemies, to be invulnerable. The solution is to find the address of the "game" variable (which should reside in the data segment or a function's stack), and follow all the pointers until you find the address of the health variable.

Some tools, e.g. Cheat Engine, have functionality to automate this, and attempt to find the pointer chain by themselves. You will probably have to resort to reverse-engineering for more complicated cases, though.

Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
  • 2
    Very nice example thanks, so all game hacks are relying on static pointers? Meaning the root of the pointer chain must be static somewhere along the line? – GameTrainersWTF May 28 '10 at 06:23
  • 3
    Yes, if it's in the data segment (a global variable from the source code point of view), and if we don't count ASLR. It could also be a stack variable (a local variable inside main() for example), in which case its address could vary from one system to another, and you'd need to walk the stack to find it, which is more complicated. – Vladimir Panteleev May 28 '10 at 06:29
  • I guess now i need to find out how game trainers get around ASLR lol – GameTrainersWTF May 28 '10 at 06:44
  • 3
    It's easy, just calculate the new address based on the base address the module was loaded at. For example, most executables are linked with an initial base address of 0x00400000. If you find a variable at 0x00543210, and the module was loaded at 0x76400000, the valiable will be at 0x76543210. – Vladimir Panteleev May 28 '10 at 06:49
  • Ah that makes a lot of sense, also explains why the last 3 numbers on my variable didn't change and only the first part did. Thanks you have been very helpful!!! – GameTrainersWTF May 28 '10 at 06:53
2

Discovery of the access pointers is quite cumbersome and static memory values are difficult to adapt to different compilers or game versions.

With API hooking of malloc(), free(), etc. there is a different method than following pointers. Discovery starts with recording all dynamic memory allocations and doing memory search in parallel. The found heap memory address is then reverse matched against the recorded memory allocations. You get to know the size of the object and the offset of your value within the object. You repeat this with backtracing and get the jump-back code address of a malloc() call or a C++ constructor. With that information you can track and modify all objects which get allocated from there. You dump the objects and compare them and find a lot more interesting values. E.g. the universal elite game trainer "ugtrain" does it like this on Linux. It uses LD_PRELOAD. Adaption works by "objdump -D"-based disassembly and just searching for the library function call with the known memory size in it.

See: http://en.wikipedia.org/wiki/Trainer_%28games%29

Ugtrain source: https://github.com/sriemer/ugtrain

The malloc() hook looks like this:

static __thread bool no_hook = false;

void *malloc (size_t size)
{
    void *mem_addr;
    static void *(*orig_malloc)(size_t size) = NULL;

    /* handle malloc() recursion correctly */
    if (no_hook)
        return orig_malloc(size);

    /* get the libc malloc function */
    no_hook = true;
    if (!orig_malloc)
        *(void **) (&orig_malloc) = dlsym(RTLD_NEXT, "malloc");

    mem_addr = orig_malloc(size);

    /* real magic -> backtrace and send out spied information */
    postprocess_malloc(size, mem_addr);
    no_hook = false;

    return mem_addr;
}

But if the found memory address is located within the executable or a library in memory, then ASLR is likely the cause for the dynamic. On Linux, libraries are PIC (position-independent code) and with latest distributions all executables are PIE (position-independent executables).

1

EDIT: never mind it seems it was just good luck, however the last 3 numbers of the pointer seem to stay the same. Perhaps this is ASLR kicking in and changing the base image address or something?

aaahhhh my bad, i was using %d for printf to print the address and not %p. After using %p the address stayed the same

#include <stdio.h>

int *something = NULL;

int main()
{
    something = new int;
    *something = 5;

    fprintf(stdout, "Address of something: %p\nValue of something: %d\nPointer Address of something: %p", &something, *something, something);
    getchar();
    return 0;
}
GameTrainersWTF
  • 235
  • 1
  • 2
  • 6
1

Example for a dynamicaly allocated varible

The value I want to find is the number of lives to stop my lives from being reduced to 0 and getting game over.

  1. Play the Game and search for the location of the lifes variable this instance.
  2. Once found use a disassembler/debugger to watch that location for changes.
  3. Lose a life.
  4. The debugger should have reported the address that the decrement occurred.
  5. Replace that instruction with no-ops

Got this pattern from the program called tsearch


A few related websites found from researching this topic:

dash-tom-bang
  • 17,383
  • 5
  • 46
  • 62
mikek3332002
  • 3,546
  • 4
  • 37
  • 47
  • Yeah fairly straight forward stuff if want to prevent myself from dieing but I wan't to read/change the actual value instead of cancelling it out – GameTrainersWTF May 28 '10 at 05:59
  • Not that familar, but you could possibly grab the address the addess that it is using. Also don't have to use No-ops you can fill it with anything eg Jumps. – mikek3332002 May 28 '10 at 06:28
  • I tried making a code cave in my program, i changed a jump that would jump to my code then jump back, but for some reason when i saved it in olly, and then reloaded it, my code in the code cave turned into jibberish DB xyz commands :S I even changed the section header to add more virtual memory space, and that didn't help either :( Perhaps you know what is happening here? – GameTrainersWTF May 28 '10 at 06:43
1

The way things like Gameshark codes were figured out were by dumping the memory image of the application, then doing one thing, then looking to see what changed. There might be a few things changing, but there should be patterns to look for. E.g. dump memory, shoot, dump memory, shoot again, dump memory, reload. Then look for changes and get an idea for where/how ammo is stored. For health it'll be similar, but a lot more things will be changing (since you'll be moving at the very least). It'll be easiest though to do it when minimizing the "external effects," e.g. don't try to diff memory dumps during a firefight because a lot is happening, do your diffs while standing in lava, or falling off a building, or something of that nature.

dash-tom-bang
  • 17,383
  • 5
  • 46
  • 62