Hey a little interface I've written for my S4 League hack.
It's copying the virtual table of the given class instance and resetting
the instance's vtable pointer to point to our copy. In the copy we will
place our hooks. It also includes a function to easily call a virtual of a class.
Maybe it's useful.
VMT.h
Code:
#pragma once
#include <map>
#include <Windows.h>
class VMT
{
public:
explicit VMT( void*** pClass );
~VMT( );
void* Hook( size_t Index, void* pFunction );
void Unhook( size_t Index );
void UnhookTable( ) const;
template <typename T>
static T CallVirtual( void* pInstance, size_t Index)
{
auto VTable = *static_cast< void*** >( pInstance );
return T( VTable[ Index ] );
}
private:
size_t Count( ) const;
size_t CountFunctions;
void*** ppClassInstance;
void** pVTable;
void** pSwapTable;
std::map<size_t, void*> mapHooks;
};
VMT.cpp
Code:
#include "VMT.h"
VMT::VMT( void*** pClass )
{
ppClassInstance = pClass;
pVTable = *pClass;
CountFunctions = Count( );
pSwapTable = static_cast< void** >( VirtualAlloc( nullptr, sizeof( void* ) * CountFunctions, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ) );
memcpy( pSwapTable, pVTable, sizeof( void* ) * CountFunctions );
*ppClassInstance = pSwapTable;
}
VMT::~VMT( )
{
if ( *ppClassInstance != pVTable && pSwapTable )
UnhookTable( );
}
size_t VMT::Count( ) const
{
if ( !ppClassInstance || !pVTable )
return 0;
size_t it = 0;
while ( pVTable[ it ] )
++it;
return it;
}
void* VMT::Hook( size_t Index, void* pFunction )
{
if ( !ppClassInstance || !pVTable )
return nullptr;
auto OriginalFunction = pVTable[ Index ];
mapHooks[ Index ] = OriginalFunction;
pSwapTable[ Index ] = pFunction;
return OriginalFunction;
}
void VMT::Unhook( size_t Index )
{
pSwapTable[ Index ] = mapHooks[ Index ];
}
void VMT::UnhookTable( ) const
{
*ppClassInstance = pVTable;
VirtualFree( pSwapTable, 0, MEM_RELEASE );
}
usage of CallVirtual:
Code:
using tEndScene = HRESULT( __stdcall* )( IDirect3DDevice9* );
auto retValue = VMT::CallVirtual<tEndScene>( pDevice, 42 )( pDevice );
TODO:
- add normal vtable function replace (without copying the whole table)