简体   繁体   中英

How to navigate through methods of a vtable?

I have an assignment for university which requires me to access the vtable of a class. I need to write a function (here called pb) which takes a pointer to an object as an argument as well as an integer, and then just prints the output of the methods of the class. I have managed to access the first function, but I don't know how to access the second function. Here's the code I have so far:

typedef int(*firstFun)();
typedef int(*secondFun)(int);

class B {
public:
    virtual int __cdecl first() = 0;
    virtual int __cdecl second(int) = 0;
};

class D : public B {
public:
    virtual int __cdecl first() { return 42; }
    virtual int __cdecl second(int x) {
        return first() + x; }
};

void pb(B* object, int x) {
    unsigned int adressVTable = *(unsigned int*)object;
    unsigned int adressVTable2; //yet unknown
    firstFun bFirst = (firstFun)(*(unsigned int*)(adressVTable));
    secondFun bSecond = (secondFun)(*(unsigned int*)(int)(adressVTable2));
    int f=bFirst();
    int s=bSecond(x);
    printf("First: %d, second: %d", f, s);
}

In conclusion, how to get bSecond to work for second(int) like bFirst works for first()?

The vTable is just an array of function pointers, so just an array of pointers. If the target process is x86 then just add 0x4 to the address of the first pointer and you will get the second pointer in the vtable. If the target process is x64, add 0x8 because that's the size of a pointer on that architecture.

Secondly, you're defining these as cdecl function which isn't going to work how you've planned. Virtual functions / member functions are __thiscall, which require the this pointer to be passed in ECX. So you need to typedef the function pointers correctly and pass the thisptr as the first argument.

Tested working:

typedef int(__thiscall *firstFun)(void* thisptr);
typedef int(__thiscall *secondFun)(void* thisptr, int);

class B 
{
public:
    virtual int first() = 0;
    virtual int second(int) = 0;
};

class D : public B 
{
public:
    virtual int first() { return 42; }
    virtual int second(int x) 
    {
        return first() + x;
    }
};

void pb(B* object, int x) 
{
    unsigned int adressVTable = *(unsigned int*)object;
    unsigned int adressVTable2 = adressVTable + 0x4;
    firstFun bFirst = (firstFun)(*(unsigned int*)(adressVTable));
    secondFun bSecond = (secondFun)(*(unsigned int*)(adressVTable2));
    int f = bFirst(object);
    int s = bSecond(object, x);
    printf("First: %d, second: %d", f, s);
}

int main()
{
    D obj;

    pb(&obj, 5);

    getchar();

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM