2019-03-21 20:18:31 +01:00
# include "common.hpp"
# include "detour_hook.hpp"
# include "logger.hpp"
# include "memory/handle.hpp"
2019-06-23 22:00:18 +02:00
# include <MinHook.h>
2019-03-21 20:18:31 +01:00
namespace big
{
detour_hook : : detour_hook ( std : : string name , void * target , void * detour ) :
m_name ( std : : move ( name ) ) ,
m_target ( target ) ,
m_detour ( detour )
{
fix_hook_address ( ) ;
if ( auto status = MH_CreateHook ( m_target , m_detour , & m_original ) ; status = = MH_OK )
{
LOG_INFO ( " Created hook '{}'. " , m_name ) ;
}
else
{
throw std : : runtime_error ( fmt : : format ( " Failed to create hook '{}' at 0x{:X} (error: {}) " , m_name , reinterpret_cast < std : : uintptr_t > ( m_target ) , MH_StatusToString ( status ) ) ) ;
}
}
detour_hook : : ~ detour_hook ( ) noexcept
{
if ( m_target )
{
MH_RemoveHook ( m_target ) ;
}
LOG_INFO ( " Removed hook '{}', " , m_name ) ;
}
void detour_hook : : enable ( )
{
if ( auto status = MH_EnableHook ( m_target ) ; status = = MH_OK )
{
LOG_INFO ( " Enabled hook '{}'. " , m_name ) ;
}
else
{
throw std : : runtime_error ( fmt : : format ( " Failed to enable hook 0x{:X} ({}) " , reinterpret_cast < std : : uintptr_t > ( m_target ) , MH_StatusToString ( status ) ) ) ;
}
}
void detour_hook : : disable ( )
{
if ( auto status = MH_DisableHook ( m_target ) ; status = = MH_OK )
{
LOG_INFO ( " Disabled hook '{}' " , m_name ) ;
}
else
{
LOG_ERROR ( " Failed to disable hook '{}'. " , m_name ) ;
}
}
DWORD exp_handler ( PEXCEPTION_POINTERS exp , std : : string const & name )
{
return exp - > ExceptionRecord - > ExceptionCode = = STATUS_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH ;
}
void detour_hook : : fix_hook_address ( )
{
__try
{
auto ptr = memory : : handle ( m_target ) ;
while ( ptr . as < std : : uint8_t & > ( ) = = 0xE9 )
{
ptr = ptr . add ( 1 ) . rip ( ) ;
}
m_target = ptr . as < void * > ( ) ;
}
__except ( exp_handler ( GetExceptionInformation ( ) , m_name ) )
{
[ this ] ( )
{
throw std : : runtime_error ( fmt : : format ( " Failed to fix hook address for '{}' " , m_name ) ) ;
} ( ) ;
}
}
}