4

I'm fairly new to reverse engineering at all and I'm currently struggling to get the static offset/address of a variable of a program I've written myself.

So I've written the following program in C++, just to get some practice:

#include <iostream>
#include <Windows.h>
#include <string>

class Entity
{
public:
    Entity(int health, int max_health, int armor) : m_health{ health }, m_max_health{ max_health }, m_armor{ armor }
    {}
protected:
    int m_health;
    int m_max_health;
    int m_armor;
};

class Player : public Entity
{
public:
    Player() : Entity(200, 400, 50)
    {}
    void heal() { m_health = m_max_health; }
    int get_health() { return m_health; }
private:
};

int main()
{
    Player player;

    while (1)
    {
        std::cout << "player health: " << player.get_health() << "\n";
        Sleep(500);
    }
}

after that I've opened up the executable in x32dbg. My first step was to look for string references and then check if I can find the "player health" string. That was fairly easy and it led me to the following instructions, which represent the while loop of the executable: 1

after that I've set a breakpoint at 010C24EC(as you can see in the picture) and I've followed ESP(which is 31FE18) in dumb which led me to the value of 200 which I assume is the value of the variable so I think the address 31FE18 is the address of my variable player.m_health. Now my problem is that the address is changing every time I restart the program(which is normal), so I've written another program in C++, which reads out the Imagebase of the other process so I thought that when I subtract the address of my variable from my Imagebase, I could get the static offset that is always going to lead me to the correct variable when I add it to the imagebase.

I'm quite sure that I missunderstood some things and I would be really happy if someone could help me out, since I've really spent some time on trying to figure this out on my own but none of the things I've tried worked so far.

Thanks in advance.

Greets Steven

3
  • In your case the Player object is allocated on the stack. Try placing it in the global scope if you want a fixed address.
    – mrexodia
    Commented Jul 24, 2018 at 18:07
  • @mrexodia Thanks for your response. I've succesfully done so before already, but how would I manage to get a fixed address (or calculate whatever the players address is going to be) when the player is a local variable?
    – Gee
    Commented Jul 24, 2018 at 19:43
  • Generally you don’t because players are generally not stored on the stack :) However, if you can somehow extract a stack address at a known location in the call stack you could do it. For example the main thread’s initial stack - x should give you the stack address of the player object since it’s allocated on the stack at the beginning of main. Did you check out the cheat engine tutorial? Usually you find a known location in the code/data that (indirectly) references the player object to get a pointer to the player in a stable manner.
    – mrexodia
    Commented Jul 24, 2018 at 20:34

1 Answer 1

4

Note: This does not answers the question using x32dbg/ollydbg, but another tool. (I can't seem to be able to post a comment). My apologies if it is off topic.

You can try with Cheat engine (CE).

If yes, download the installer-less release, because the installer includes crap:

enter image description here

I assume you downloaded it and extracted it at this point.

This software has a really nice integrated tutorial which is another .exe shipped in the folder. Read more about it HERE (it is for 64 bits, but it should give you an idea on how to run the 32 bit tutorial). Try to go through it (or skip the steps - bottom right corner), and at some point (step 6 and 8) your problem will be addressed (no pun intended).

Good luck :)


Addendum

Reading from the comments you posted below

  • I'm usually not lucky enough to pick the right one straight away [...]

Although it is not perfect, CE has this tool called the "pointer scan" (you might already know this tool, I'm thinking about new CE users) where it kind of brute forces the offsets and goes down more than one level of depth. It might work after lots of effort.

  • So I thought learning how to use them with small self-written programs would be the smartest way of getting into it. But as @mrexodia pointed out already, player objects are usually not allocated on the stack.

Speaking more generally (I deviate from your pointer question), I think that this is a very good approach. Example : with this approach I once discovered an opcode I didn't know about / cmov (or cmovcc in manuals) while dissassembling a game of mine and therefore I knew exactly how things were laid down in the memory and in the code. Very instructive for me, definitely a +1. You could also learn about compiler optimizations by comparing the code and the generated assembly.

When it comes to more complex games, try to practise on indie games (singleplayer of course) or open source (because they are accessible). Try Assault cube (or Assault cube reloaded). This game is quite enjoyable to practise on because there are no debugging protections nor anti-cheat system, ... You can for example find pointers to the local player, or modify the game code / making your team invincible, infinite ammo and so on...

A workaround to your problem

This is an intuition and not based on facts, but I beleive that games made in virtual machines such as Java, C#, or OS features such as address randomization ... are harder to debug in assembly and could be unpredictable in terms of pointer finding, ... . A method I like to use (to find the local player, most of the time) is using "code hooking".

For example, if you want to find the address to the local player in AssaultCube (or an other game) you could find the GUI code that draws the player ammo/health on screen, because if your game displays to you that you have 100Hp, well it got to extract the value somewhere. What you could do in this case is using CE and find the Hp, finding what code accesses this address and hopefully there will be along the lines, the GUI code that intercepts this value. From there you can retreive the player base address. What is really good about this technique is that you don't have to mess around with pointers, it's a pretty straight forward way to get your player address.

The downside is that you have to inject some code to reteive it. You could inject a hand crafted program (C, C++, ...) or use a CE trainer to acheive this effect. Using a debugger at this point may help you to understand where the data comes from and hopefully find a way to get the pointer.

  • so my whole idea seems to be stupid / My biggest problem is that I'm not really a smart kind of a person / or would you say that it's a waste of time for a person like me

No it is not stupid, you can totally get it to there, to me you are definitely not "not really a smart kind of a person" because you're trying to understand low level concepts such as pointers.

I am not experienced in the reverse engineering field, I do not pretend that I know much things, but I have some "bad" questions on stackoverflow / gamedev, I clearly didn't know what I was doing but hey, I was younger and that is okay, it's part of the learning curve. At first I didn't even understand these concepts and quite a time ago, I made a "simple" mod for a game that involved assembly patching to improve the fun. There were two simple patches to make, but it took me some hours to figure out. The point I want to make is that you have to start somewhere. Kudos to you for trying !

You WILL spend or even waste, to some extent, time figuring things out, learning techniques, debugging, ... It does not come alone you know. It's like drawing, I don't think Picasso woke up one day and knew how to paint, it eventually came with practice, failures, study and frustration.

Now I realize that this does not really answers your question and my apologies, basically try the pointer scan / code hooking. I'm sure that there are more solutions to this problem, that I am not aware of.

5
  • Hey, thanks for your answer. Yeah I've done the cheat engine tutorials several times already and I also watched videos of people explaining it a little bit more in-depth. The thing is that I'm having real hard times when tracing back pointer chains using cheat engine on larger games. Most of the times I can trace it back for like 2 or 3 offsets and then I just get way too many possible base pointers.
    – Gee
    Commented Jul 26, 2018 at 10:28
  • And I'm usually not lucky enough to pick the right one straight away and doing trial and error on hundreds of addresses doesnt seem like a proper way of doing it either. So I was looking on better ways to do it and I found a bunch of possible solutions and the most recommended one was to use a debugger like x32dbg. So I thought learning how to use them with small self-written programs would be the smartest way of getting into it. But as @mrexodia pointed out already, player objects are usually not allocated on the stack, so my whole idea seems to be stupid but atleast I learned some out of it.
    – Gee
    Commented Jul 26, 2018 at 10:35
  • Most of the big games have some public offset dumpers anyway, but I just really want to learn how to do these things on my own to build up strong knowledge. My biggest problem is that I'm not really a smart kind of a person and getting into this is really hard to me. But on the other hand it's so much fun to learn new things and I'm really willing to spend some time on it. But do you think having a passion for it is actually enough to ever build up some good knowledge or would you say that it's a waste of time for a person like me? Sorry for this weird question.
    – Gee
    Commented Jul 26, 2018 at 10:48
  • 1
    I edited my answer, I wrote what came to mind, sorry if it may seem a bit chaotic ;)
    – Riptide
    Commented Jul 26, 2018 at 22:34
  • 1
    Wow, thank you so much for this really detailed and motivating answer. :)
    – Gee
    Commented Jul 27, 2018 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.