I generally used these pre-created functions:
Code:
void MakeJMP ( BYTE* pAddress, DWORD dwJumpTo, DWORD dwLen ) {
DWORD dwOldProtect, dwBkup, dwRelAddr;
VirtualProtect ( pAddress, dwLen, PAGE_EXECUTE_READWRITE, &dwOldProtect );
dwRelAddr = ( DWORD ) ( dwJumpTo - ( DWORD ) pAddress ) - 5;
*pAddress = 0xE9;
* ( ( DWORD * ) ( pAddress + 0x1 ) ) = dwRelAddr;
for ( DWORD x = 0x5; x < dwLen; x++ ) * ( pAddress + x ) = 0x90;
VirtualProtect ( pAddress, dwLen, dwOldProtect, &dwBkup );
return;
}
void* DetourFunction ( BYTE* src, const BYTE* dst, const int len ) {
DWORD dwBack;
BYTE* jmp = ( BYTE* ) malloc ( len + 5 );
VirtualProtect ( src, len, PAGE_EXECUTE_READWRITE, &dwBack );
memcpy ( jmp, src, len );
jmp += len;
jmp[0] = 0xE9;
* ( DWORD* ) ( jmp + 1 ) = ( DWORD ) ( src + len - jmp ) - 5;
src[0] = 0xE9;
* ( DWORD* ) ( src + 1 ) = ( DWORD ) ( dst - src ) - 5;
for ( int i = 5; i < len; i++ )
src[i] = 0x90;
VirtualProtect ( src, len, dwBack, &dwBack );
return ( jmp - len );
}
Examples:
So for DetourFunction: (From my MW3 Hook)
Code:
typedef int (__cdec* tDraw2D)(int a1);
tDraw2D Draw2D = NULL;
DetourFunction((BYTE*)OFFS_DRAW2D, (BYTE*)&Draw2DHook, 0x5);
int Draw2DHook(int a1)
{
__asm pushad; //Preserve stack beforehand
//Hack stuff
__asm popad; //Get back stack
Draw2D(a1); //Then call origional game code and return to normal execution
}
And for MakeJMP:
Code:
DWORD dwReturn = (OFF_DRAW2D + 5);
__declspec(naked) void Draw2D()
{
__asm
{
//Do overwritten code here
//Preserve stack
pushad;
pushfd;
}
Draw2DWrapper(); //Hack stuff
__asm
{
//Restore stack
popfd;
popad;
jmp [dwReturn]; //Return to game code
}
}
MakeJMP((PBYTE)OFF_DRAW2D, (DWORD)Draw2D, 5);
---------- Post added at 01:44 AM ---------- Previous post was at 01:42 AM ----------
EDIT:
The main difference between DetourFunction and MakeJMP is that you don't have a variable to automatically execute the code overwritten so you'll have to do it manually. For beginners and in general, DetourFunction is easier to use... (Once you get your typedef right.)