Monday, February 25, 2019

Reversing C++ codes tutorial series: Classes and its members

In this post, I will be sharing how C++ classes are constructed and its members are accessed.

Key takeaways:
1. Identifying functions written using C++
2. Identifying constructor functions
3. Rebuilding the Class structures using Struct in IDA
4. Understanding how the member variables are accessed in an object.

The example code has a single class. Member functions in the class are all static. All the objects created from the class are stored in local variable and not in the dynamic memory (Heap).

Let me begin with this C++ code:

Explanations on what the above code does
The above code first define a "Fighters" class. The "Fighters" class contains private variable "Stealth" which is only accessible by functions inside the "Fighters" class. The public variable "model","Health" and "Strength" are accessible from outside the "Fighters" class. There are two public member functions "add_steath" and "printinfo" that can be used to interact with the variables in the objects of the "Fighters" class. Finally is the constructor function that was used to initialize the variables in the objects of the "Fighters" class with default values.

Inside the main function, a object class of type "Fighters" is created and its information is displayed via "printinfo". Next, a "F16" class is created and the "Health" variable is updated to 100. Finally, a "F35" class is created with the variables "Health" and "Strength" updated. The "Stealth" variable can only be updated indirectly via the "add_stealth" function. As the "Stealth" variable is private.

Analysing the compiled version of the above C++ code
Let's look at the main() of the binary.

1. Identifying functions written using C++
Let begin by locating those functions written with C++. These functions that have an argument passed into them via register ECX. This argument is the "This" pointer. The "This" pointer is used to referenced the instance of the object and its contents (member functions and variables).

2. Identifying constructor functions
Among these C++ functions, we have to locate the constructor. This function is called whenever an instance of an object is created. Therefore, this function is called before the member functions of the class. The function that contained code that initializes the member variables would likely be the constructor.

This is the constructor of the "Fighters" class.

3. Rebuilding the Class structures using Struct in IDA
The ECX register is passed into the constructor function from the caller. ECX contained the "This" pointer. The "This" pointer value is then stored in the local variable "var_10". Next you will observe how values are stored into offsets from "var_10". At this point it would be useful to re-create the struct of the objects of the "Fighters" class.
To do so we can go to View->Open subviews->Structures or Shift+F9

Given the offset values and the types of data being initialized at the various offsets.
We will then create the structure of the "Fighers" class as shown below.

We can compare the struct to the "Fighters" class definition code as shown below.
Fighters() {
  model = "Default Model";
  Health = 50;
  Strength = 50;
  Stealth = 0;

4. Understanding how the member variables are accessed in an object.
We will apply the struct offsets to the constructor by Right clicking on the offset and choose "Structure offset".

Next we can go on to label the offsets in main and other member functions of "Fighters" class.

After labeling the offsets and member functions we can have a better understanding of how the members of the class are accessed.

No comments:

Post a Comment