A virtual function is essentially a function in a class, that allows inherited classes to overwrite that function. On assembly level, this means that the compiler generates a table of pointers to functions, which are then called instead of calling the function directly. This allows inherited classes to easily overwrite the virtual function in the class instance. ex:
2521a783 2521a825 25220052 25228252As you can see, it consists merely pointers, that point to the functions themselves.
(I am working on my paint skills):
With this information, we can actually easily replace the address that exists within the vmt with a pointer to our own function, while preserving the original function pointer for later use.
I've coded a little example code here just for the sake of consistency;
class VirtualTable { public: virtual void VirtualFunction01( void ); }; void VirtualTable::VirtualFunction01( void ) { cout << "VirtualFunction01 called" << endl; } //we use this to store and call the original function inside our custom one typedef void ( __thiscall* VirtualFunction01_t )( void* thisptr ); VirtualFunction01_t g_org_VirtualFunction01; //our custom function void __fastcall hk_VirtualFunction01( void* thisptr, int edx ) { cout << "Custom function called" << endl; //call the original function g_org_VirtualFunction01(thisptr); } int _tmain(int argc, _TCHAR* argv[]) { VirtualTable* myTable = new VirtualTable(); //get the pointer to the actual virtual method table from our pointer to our class instance void** base = *(void***)myTable; DWORD oldProtection; //one way to remove page protection(not the best but this is an example only) VirtualProtect( &base[0], 4, PAGE_EXECUTE_READWRITE, &oldProtection ); //save the original function g_org_VirtualFunction01 = (VirtualFunction01_t)base[0]; //overwrite base[0] = &hk_VirtualFunction01; //restore page protection VirtualProtect( &base[0], 4, oldProtection, 0 ); //call the virtual function (now hooked) from our class instance myTable->VirtualFunction01(); system("pause"); return 0; }
Output:
Custom function calledVirtualFunction01 called