Detouring Library

Joined
Apr 23, 2006
Messages
415
Reaction score
45
Well, I'm looking for a Detouring Library that works fine with GunZ. I was actually using CDetour, it works mostly fine, but I found out some incompatibilities with x64, plus, I'm wanting to upgrade to Visual Studio 2008, and CDetour conversion for 2008 is giving me a bunch of errors. I've already tried Micro$oft Detours, but it isn't that good for Gunz. That's it, I would really appreciate all the suggestions. Thanks.
 
Writing your own isn't terribly complicated.

Example.cpp:

Code:
#include "hiJackr.h"

PBYTE _LastFunction;
PBYTE _LastHook;
DWORD _LastReturnAddress;
CRITICAL_SECTION CS;
BOOL iCS = FALSE;

PBYTE Detour( PBYTE Offset, PBYTE Hook )
{
	PBYTE _Prologue = new BYTE[_HookLength];
	DWORD OldProtect;

	if( !iCS )
	{
		InitializeCriticalSection( &CS );
		iCS = TRUE;
	}

	memcpy( _Prologue, &Offset[0], _HookLength );

	VirtualProtect( Offset, _HookLength, PAGE_EXECUTE_READWRITE, &OldProtect );

	Offset[0] = 0xE8;
	*( DWORD_PTR * ) ( &Offset[1] ) = ( DWORD_PTR ) ( Hook - Offset ) - _HookLength;

	VirtualProtect( Offset, _HookLength, OldProtect, &OldProtect );

	return( _Prologue );
}

void RepairFunction( BYTE *Offset, BYTE *Buffer )
{
	DWORD OldProtect;
	
	VirtualProtect( Offset, _HookLength, PAGE_EXECUTE_READWRITE, &OldProtect );

	for( UINT i = 0; i < _HookLength; i++ )
		*( ( PBYTE ) Offset + i ) = Buffer[i];

	VirtualProtect( Offset, _HookLength, OldProtect, &OldProtect );
}

void RepairDetour( )
{
	Detour( ( PBYTE ) _LastFunction, ( PBYTE ) &_LastHook );
	*( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) = _LastReturnAddress;
	LeaveCriticalSection( &CS );
}

Example.h:

Code:
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <intrin.h>

#ifndef _M_IX86
	#ifndef _M_X64
		#error Platform not supported: build for x86 or x86-64 only.
	#endif
#endif

#ifdef _M_IX86
	#define _HookLength 5
#elif _M_X64
	#define _HookLength 9
#endif

#define _Prologue( _Prologue ) \
	_LastFunction = ( PBYTE ) ( ( DWORD ) _ReturnAddress( ) - _HookLength ); \
	RepairFunction( ( PBYTE ) _LastFunction, _Prologue );

#define _Epilogue( this ) \
	EnterCriticalSection( &CS ); \
	_LastHook = ( PBYTE ) this; \
	*( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) -= _HookLength; \
	_LastReturnAddress = ( DWORD ) *( ( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) \
			+ 8 / sizeof( DWORD_PTR * ) ); \
	*( ( DWORD_PTR * ) _AddressOfReturnAddress( ) + 4 / sizeof( DWORD_PTR * ) ) = ( DWORD_PTR ) RepairDetour; \
	return;

extern PBYTE _LastFunction;
extern PBYTE _LastHook;
extern DWORD _LastReturnAddress;
extern CRITICAL_SECTION CS;
extern BOOL iCS;

PBYTE Detour( PBYTE Offset, PBYTE Hook );
void RepairFunction( PBYTE Offset, PBYTE Buffer );
void RepairDetour( );

Terribly organized, but this does serve well as an example.
 
Upvote 0
You missed what I was trying to say. But I now assume this is was never meant to return to the original function.

Oh, yes it does.

Code:
#define _Prologue( _Prologue ) \
	_LastFunction = ( PBYTE ) ( ( DWORD ) _ReturnAddress( ) - _HookLength ); \
	RepairFunction( ( PBYTE ) _LastFunction, _Prologue );

#define _Epilogue( this ) \
	EnterCriticalSection( &CS ); \
	_LastHook = ( PBYTE ) this; \
	*( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) -= _HookLength; \
	_LastReturnAddress = ( DWORD ) *( ( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) \
			+ 8 / sizeof( DWORD_PTR * ) ); \
	*( ( DWORD_PTR * ) _AddressOfReturnAddress( ) + 4 / sizeof( DWORD_PTR * ) ) = ( DWORD_PTR ) RepairDetour; \
	return;


_Epilogue repairs and returns.
 
Upvote 0
Thanks gWX0, I'm gonna take a look at it. Btw someone have any clue about why some detouring libraries fails at returning to the original function when it has classes or structures as parameters?
 
Last edited:
Upvote 0
Oh, yes it does.

Code:
#define _Prologue( _Prologue ) \
    _LastFunction = ( PBYTE ) ( ( DWORD ) _ReturnAddress( ) - _HookLength ); \
    RepairFunction( ( PBYTE ) _LastFunction, _Prologue );

#define _Epilogue( this ) \
    EnterCriticalSection( &CS ); \
    _LastHook = ( PBYTE ) this; \
    *( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) -= _HookLength; \
    _LastReturnAddress = ( DWORD ) *( ( ( DWORD_PTR * ) _AddressOfReturnAddress( ) ) \
            + 8 / sizeof( DWORD_PTR * ) ); \
    *( ( DWORD_PTR * ) _AddressOfReturnAddress( ) + 4 / sizeof( DWORD_PTR * ) ) = ( DWORD_PTR ) RepairDetour; \
    return;
_Epilogue repairs and returns.


Ahhh! I see. So you can't return to the function in the middle of the hook.
 
Upvote 0
Ahhh! I see. So you can't return to the function in the middle of the hook.

Er, the idea is you run _Prologue and _Epilogue to represent the beginning and ending of your hook. _Epilogue returns back to your function.

cerealnp - Detouring Library - RaGEZONE Forums
 
Upvote 0
CDetour does not have any compatibility issues with x64, and in fact it cannot, because x64s run gunz in an x86 emulator

to get CDetour working with 2008, exclude CDetourDis and include detours.h (microsoft detours 1.5) instead

the struct thing is probably caused by not defining the calling convention of your hook functions

and gWX0, your detour library blows
 
Upvote 0
CDetour does not have any compatibility issues with x64, and in fact it cannot, because x64s run gunz in an x86 emulator

to get CDetour working with 2008, exclude CDetourDis and include detours.h (microsoft detours 1.5) instead

the struct thing is probably caused by not defining the calling convention of your hook functions

and gWX0, your detour library blows

1) Yes, CDetour does have issues with x64, as in it cannot compile for x64 platforms......................

2) On 64-bit platforms, Gunz isn't ran in an "emulator"; though it is running under "emulation mode", using what you could call a pseudo-emulator at best.

3) What..? Remove the proper CDetour definitions and use the Microsoft Detours build? That changes the library entirely, making it a hybrid of MS Detours and CDetour, unless you mean to exclude all CDetour files and just use Microsoft's detours library.

4) Why would that only happen for structures or classes? Calling convention isn't the issue.

5) It works without using a run-length disassembler, which adds forward-compatibility when newer instructions are introduced and used in function prologue code.

EDIT:

Using the example:

Code:
#include "example.h"
PBYTE MBA_Prologue;

void MBA_Hook( )
{
	_Prologue( MBA_Prologue );

	MessageBoxA( 0, "Hooked!", "", MB_OK );

	_Epilogue( MBA_Hook );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
	MBA_Prologue = Detour( ( PBYTE ) MessageBoxA + 5, ( PBYTE ) &MBA_Hook );
	MessageBoxA( 0, "Works fine", "???", MB_OK );

	return( 0 );
}
 
Last edited:
Upvote 0
1) Yes, CDetour does have issues with x64, as in it cannot compile for x64 platforms......................

2) On 64-bit platforms, Gunz isn't ran in an "emulator"; though it is running under "emulation mode", using what you could call a pseudo-emulator at best.

3) What..? Remove the proper CDetour definitions and use the Microsoft Detours build? That changes the library entirely, making it a hybrid of MS Detours and CDetour, unless you mean to exclude all CDetour files and just use Microsoft's detours library.

4) Why would that only happen for structures or classes? Calling convention isn't the issue.

5) It works without using a run-length disassembler, which adds forward-compatibility when newer instructions are introduced and used in function prologue code.

EDIT:

Using the example:

Code:
#include "example.h"
PBYTE MBA_Prologue;

void MBA_Hook( )
{
    _Prologue( MBA_Prologue );

    MessageBoxA( 0, "Hooked!", "", MB_OK );

    _Epilogue( MBA_Hook );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
    MBA_Prologue = Detour( ( PBYTE ) MessageBoxA + 5, ( PBYTE ) &MBA_Hook );
    MessageBoxA( 0, "Works fine", "???", MB_OK );

    return( 0 );
}

CDetourDis = Microsoft Detour File renamed.
 
Upvote 0
Back