Completely overriding the VMT (Virtual Method Table)

1.2k views Asked by At

I'm calling a virtual method on the vmt by dereferencing until I get the pointer to the method.

This is all good however, how would I completely change the pointer to the VM table on the object?

Example:

PP A; // points to its default VM table

PP B; // points to a completely different VM table

A->MethodOne() // calls as mentioned above

B->MethodOne() // calls a completely different method since we override its pointer to the VM table to an alternate table with different method pointers

How would I accomplish this?

My Code:

#include <Windows.h>
#include <iostream>

class PP
{
public:
    PP() { }
    ~PP() { }

    virtual void MethodOne() { std::cout << "1" << std::endl; }
    virtual void MethodTwo() { std::cout << "2" << std::endl; }
};

typedef void (*MyFunc)(void);

int main()
{
    PP* A = new PP();

    //(*(void(**)(void))(*(DWORD*)A + (4*1)))();
                      
    ( *(MyFunc*) ( *(DWORD*)A + (4*0) ) )(); // call index 0 (4bytes*0)
    A->MethodOne();
    A->MethodTwo();
    system("PAUSE");
    delete A;
    return 0;
}
2

There are 2 answers

0
1201ProgramAlarm On BEST ANSWER

Since the usual method of deriving another class won't work for you, there are three solutions I can think of.

  1. Change the vtable pointer. This is non-portable and has many ways to just go horribly wrong. Assuming the vtable is at the start of the class (which it is for simple classes in the WinAPI), you can replace that pointer with one to a table of your own.

    *(void **)A = newVtable;
    

with newVtable defined with appropriate pointers-to-member-functions. You'll have to use extreme caution to set this up. It could also mess up deletes and exception handling.

  1. Create your own vtable. Define a class with the required pointer-to-method-functions, then define a pointer in your class to one of these. You can then change the pointer to the table as necessary. This would be a bit more verbose on calling, although you could define other member functions to hide the ugly code.

    class vtable;
    
    class PP {
    public:
        PP();
        ~PP() { }
    
        void MethodOne() { std::cout << "1" << std::endl; }
        void MethodTwo() { std::cout << "2" << std::endl; }
    
        const vtable *pVtable;
    };
    
    class vtable {
    public:
        void (PP::*MethodOne)();
    };
    
    vtable One = {&PP::MethodOne};
    vtable Two = {&PP::MethodTwo};
    
    PP::PP(): pVtable(&One) { }
    
    void main() {
        PP* A = new PP();
    
    
        A->pVtable = &One;
    
        // call with
        (A->*(A->pVtable->MethodOne))();    // calls MethodOne
    
        A->pVtable = &Two;
        (A->*(A->pVtable->MethodOne))();    // calls MethodTwo
    }
    

(Compiled and tested with VS2015 Community). This would be portable and safe.

  1. Define method pointers within the class, and update them individually.
2
Agata Staniak On

If I understand your question correctly - you want to replace the VM table of an object at runtime. Not sure why you use C++ language for such low level modifications?

Anyways, Microsoft C/C++ supports something called a "naked" calling convention (as opposed to "stdcall", "fastcall" etc. that differ in how/what order params are passed to a function and whether they're passed on a stack or in registers). In naked calling convention, YOU have absolute control of how you pass params - you write your own inline assembly snippets responsible for putting stuff on stack and stack unwinding.

https://msdn.microsoft.com/en-us/library/5ekezyy2.aspx

You could, for example, use the naked calling convention for the constructor (if compiler won't complain) and pass in the new VM table as a "hidden" param, just like "this" param is a "hidden" param passed to member functions (in the "thiscall" calling convention). And you could do your magic in inline assembly to replace the VM in the constructor.

This whole thing seems like a horrible, fragile idea though because a new version of the compiler that changes its internals (normally not exposed to you) may potentially break your code. If you really need some sort of dynamic mechanism of choosing what method to call, sounds like you should implement your own mechanism instead of piggybacking as a hack on top of C++'s VMT mechanism.