Virtual function is used to help code polymorphism and it is a key feature of inheritance, allowing developers to write flexible code. However, this feature can make the code more challenging to comprehend and analyze, especially for reverse engineers. Complicating the flow of execution while determining which function to invoke at runtime based on the object's type.
To see how it works, I have coded a simple application in C++:
#include <iostream>
class Animal {
public:
virtual void sound(){
std::cout << "Default Sound\n";
};
virtual void kind() {
std::cout << "Default Kind\n";
}
};
class Dog : public Animal {
public:
void sound() override {
std::cout << "Woof\n";
};
void kind() override {
std::cout << "Bulldog\n";
}
};
void vcall (Animal *a){
a->sound();
a->kind();
}
int main () {
Dog* dawg = new Dog();
Animal* anim = new Animal();
vcall(dawg);
vcall(anim);
delete dawg;
delete anim;
return 0;
}
Our Animal class is the base class. And with Dog sub-class,
Running it with radare2 (UNIX-like Disassembler/Debugger. You can use your favorite):
Firstly, it allocates 8 bytes for the pointer using the
It does the same process for the base class. 2 different areas in the memory have been allocated for 2 different classes. Each being passed into the
Here, we see an unusual way of calling a function. That, is the
What is a Virtual Function Table?
VFTable is simply an array that stores pointers to virtual functions. That being said, each class with virtual functions has its own VFTable. And the compiler adds an additional
As the diagram shows, 2 different VFTable can have an entry that points to the same function address.
If we get to our application, first argument is the entry address of the VFTable (vpointer).
After getting the entry address, it dereferences the pointer and goes to that VFTable.
First call is going to be our
Even though it is pain in the arse to reverse engineer, it is fun to mess with virtual functions and polymorphic code.