Changing the vtable pointer
August 14th, 2009 § Leave a Comment
Most compilers implement dynamic binding by using a vtable whose pointer resides at the beginning of each object’s memory footprint (something along the lines of [vtable-pointer|..members..], if we are not considering virtual inheritance).
Keeping this idea in mind, why don’t we go ahead and attempt to change that vtable pointer?
#include <iostream>
using std::cout;
struct A {
virtual void f () { cout << "a:" << n; }
A () : n(1) {}
int n;
};
struct B : A {
void f () { cout << "b:" << n; }
B () { n = 2; }
};
int main () {
A *a = new A();
A *b = new B();
// lets change a's vtable to b's
*reinterpret_cast<void**>(a) =
*reinterpret_cast<void**>(b);
a->f(); // hurray, B::f() is invoked!
}
Notice we surely did not touch the object itself, since the member did not change.
One extra thing i would like to mention is that i have tried to change specific entries inside the vtable, but the compiler marks that memory area as read-only and therefore throws an exception whenever modification attempts are made. Here is the attempted piece of code:
#include <iostream>
using std::cout;
struct A {
virtual void f () { cout << "f"; }
virtual void g () { cout << "g"; }
};
int main () {
A *a = new A();
void **vtable = *reinterpret_cast<void***>(a);
vtable[0] = vtable[1];
a->f();
}
This change to the vtable would make the call to f() actually invoke g().