Monday, February 25, 2019

Reversing C++ codes tutorial series: Inheritance and Dynamic memory

In this post, I will be sharing a key concept in OOP; Inheritance. I will also make use of dynamic memory to store the new objects.

Key takeaways:
1. Identify the differences between object creation of parent from child class.
2. Track the creation of objects using dynamic memory (Heap).

Assumptions
The example code only has a single class and 1 child class. The member functions in class are all static.

Let me begin with this C++ code:
#include "pch.h"
#include <iostream>
#include <string>
using namespace std;
//Parent Class
class Animal
{
public:
string name;
string food;
int legs;
Animal();
~Animal();
void Naming();
//virtual void Eating(string food);
};
//Child Class
class Cats : public Animal
{
public:
Cats();
~Cats();
int toys;
void Playing();
//virtual void Meowing();
//virtual void Eating(string food);
};
//Constructor belonging to Animal class
Animal::Animal()
{
cout << "Animal class constructor called!" << endl;
name = "Default animal";
food = "Animal food";
legs = 4 ;
}
//Destructor belonging to Animal class
Animal::~Animal()
{
cout << "Animal class destroyer called!" << endl;
}
//Definition of member function Naming() in Animal class
void Animal::Naming() {
cout << "My name is " << name << endl;
}
//void Animal::Eating(string food) {
// cout << "My food is " << food << endl;
//}
//Constructor belonging to Cats class
Cats::Cats()
{
cout << "Cats class constructor called!" << endl;
name = "Cats";
food = "Cats food";
toys = 1;
}
//Destructor belonging to Cats class
Cats::~Cats()
{
cout << "Cats class destroyer called!" << endl;
}
//Definition of member function Playing() in Cat class
void Cats::Playing() {
cout << "I have " << toys << " toy(s)." << endl;
}
//void cats::meowing() {
// cout << "i love to meow!" << endl;
//}
//
//void cats::eating(string food) {
// cout << "i love to eat " << food << endl;
//}
int main()
{
Animal Generic_Animal;
Animal* pGeneric_Animal = &Generic_Animal;
pGeneric_Animal->Naming();
cout << "\n\n" << endl;
string Cat1food;
Cats* pCat1 = new Cats;
pCat1->name = "Garfield";
pCat1->Naming();
pCat1->Playing();
//pCat1->food = "Fish";
//pCat1->Naming();
//pCat1->Eating(Cat1food);
//pCat1->Meowing();
getchar(); //added to prevent console from closing after code is executed.
}


Explanation on what the above code does
Please ignore the commented out codes they will be un-commented for next blog post.

Explanation on what the above code does
The above code first define a "Animal" class. The "Animal" class contains 3 public variables "name", "food" and "legs". It also has 3 member functions. "Animal()" is the constructor while "~Animal()" is the destructor function. "Naming" is a member function implemented to interact with the "name" variable in the object of "Animal" class.

Next is the "Cats" class with 1 public variable "toys". It also have constructor and destructor functions. "Playing" is a member function implemented to interact with the "toys" variable in the object of "Cats" class.

Inside the main function, an object "Generic_Animal" of type class "Animal" is created. And its member function "Naming" is called. Then an object pointed by "pCat1" of type class "Cats" is created. Note that this object is created using the "new" keyword. Finally, the member functions "Naming" and "Playing" are called.


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


I have gone ahead to label the constructor of Animal class as "FN_Constructor_Animal", functions related to using of std:string as "FN_String_stuff_XX", function related to use of "New" keyword as "FN_New" and mem copy as FN_MemCopy". If you have trouble understanding how/why I labeled these functions please leave a comment I will explain with more details.

1. Identify the differences between object creation of parent from child class.
For the object of type class "Animal", it is created in the "FN_Constructor_Animal" function.

Next is the creation object of type class "Cats". Very soon after the "FN_New" the "FN_Constructor_Animal" is called. This is because "Cats" is the child class of "Animal". So the object of type "Cats" will first be populated with the members of class "Animal". This is the OOP concept, Inheritance.

Following the "FN_Constructor_Animal" you will see the constructor of "Cats" where the member variables "name" and "food" are overwritten those in "Cats". An additional member variable, "toys" is appended to the object of type "Cats".
This is where you can create the struct for "Animal" and "Cats".


2. Track the creation of objects using dynamic memory (Heap).
Zooming into the construction of object type "Cats"

We notice the use of "FN_New". Inside this function contains a call to malloc(), the key is to note the return address of "FN_New" is in the Heap memory which is used to store dynamically allocated memory. The other thing to note is the value 0x38 at 0x0040127C. This is the size of the object created. So we know the size and address of the object type "Cats".

The following picture show the contents of object type "Cats" in the Heap memory. At 0x00401287 the value of EAX contained the address of the object created in Heap memory.


Next, the constructor of the "Animal" class is called and the member variables and functions are populated. The following happened at 0x00401295 after "FN_Constructor_Animal" is called.


Inside the constructor of the "Cats" class the "name" and "food" member variables are overwritten.(0x004012C4 and 0x004012D3). Do note the member variable "legs" remained unchanged but a new member variable "toys" is appended! (0x04012E1)


Knowing where the object of type "Cats" is created allowed us to trace the changes taken place inside it.

No comments:

Post a Comment