Pergunta

After a some googling I found a way to modify the VTable of a Class, but in my case I just have a pointer to my class as well as an interface to cast it to. I need to redirect one of those functions (in a DLL; no source code) to one of my functions. Problem is I don't know on which index the function is on, so in order to find it I tried scanning the VTable for the pointer to that function.

Is there any way to do this?

Here is my code so far:

typedef DWORD (__thiscall *CW_FUNC)();

class ClassWriter
{
public:
    PVOID m_hObj;
    PVOID *__vfptr;
    PVOID m_old[256];
    void SetObj(PVOID hObj)
    {
        m_hObj = hObj;
        __vfptr = *(PVOID **)hObj;
    }
    void AddOverride(int offset, PVOID newfunc)
    {
        DWORD dwNull;
        m_old[offset] = __vfptr[offset];
        VirtualProtect(__vfptr + offset * 4, 4, PAGE_EXECUTE_READWRITE, &dwNull);
        __vfptr[offset] = newfunc;
    }
    int GetOffset(PVOID func)
    {
        for (int i = 0; __vfptr[i] != NULL; i++)
        {
            if (func == __vfptr[i]) return i;
        }
    }
    CW_FUNC GetFunc(int offset)
    {
        return (CW_FUNC)m_old[offset];
    }
};

void WINAPI ChangeFunc()
{
    ClassWriter cw;
    HMODULE hMod = GetModuleHandle("dll_to_change.dll");
    IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyClass")();
    cw.SetObj(myObj);
    int d = cw.GetOffset(myObj->MyFunction);
    cw.AddOverride(d, OverrideFunction);
}
Foi útil?

Solução

So for all that view this question and don't really know how to do it now:

I'm using ollydbg, but you can use any other debugger/dumper.

Best way of doing this is putting your code into a dll. Make sure to execute your function, else the compiler won't compile it (at least for me)

void OverrideFunction()
{
    HMODULE hMod = GetModuleHandle("mydll.dll"); // If not loaded yet use LoadLibrary()
    IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyObject")(); // Get the pointer to your object
    char buffer[64];
    sprintf_s(buffer, "0x%X", OverrideFunction); // Print position of current function into buffer
    MessageBox(0, buffer, "", 0);
    myObj->MyFunction(); // Put in your function
}

Now either execute your code until the MessageBox() and open that address in your debugger or if your compiler created an export function you can just go to YourDll.OverrideFunction

Look for a line below, that is something like this (if your compiler detects names)

CALL DWORD PTR DS:[<&USER32.MessageBoxA>]

or

CALL DWORD PTR [YourDll._imp__MessageBoxA]

the next CALL after that should be your class function, in my case:

CALL DWORD PTR DS:[EAX+34]

Your offset is 0x34 which would be 52 (remember always to calculate the hex numbers). To get the index in the VTable you have to divide by 4 (size of a pointer) which would be 13 in my case.

void __fastcall NewFunc(IMyInterface *myObj, int null, (additional params)) // fastcall stores the first 2 params int ECX and EDX, thiscall stores the this-object in ECX
{
//  Your code
}

void OverrideFunction()
{
    DWORD dwNull;
    HMODULE hMod = GetModuleHandle("mydll.dll"); // If not loaded yet use LoadLibrary()
    IMyInterface *myObj = (IMyInterface*)GetProcAddress(hMod, "GetMyObject")(); // Get the pointer to your object
    PVOID *vtable = *(PVOID**)myObj; // The first int in your object is a pointer to the vtable
//  OldFunc = vtable[13]; // You might want to call your old function again, so save the pointer
    VirtualProtect(&vtable[13], 4, PAGE_EXECUTE_READWRITE, &dwNull); // Always unprotect the memory
    vtable[13] = NewFunc;
}

Now everytime MyObject calls MyFunction, NewFunc will be executed instead

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top