[READ]
Please note I'm having problems with using the detour library as my compiler is having a stick up it's ass. It should work, but then again I'm doing this from memory.
[/READ]
When using detours, you can pretty much, in idiot terms, "control" a function to do what you want (it changes how the function works as long as you use your hook).
In example, we can make the function "ZChatOutput" (Which is a client-sided chat) call a message box when that function executes. I'll be using Lance's "CDetour" library, instead of M$'s.
What we want to do is first create a library project, and add the files in the "CDetour" folder to your project, and compile. This will produce a file named "CDetour.lib" (Or <your_project_name.lib). Now, create a new project named "HookingTest" or w/e, and make it a dynamic link library. Add all the "CDetour" files and the .lib file into your projects directory, or add it in the VC++ Directories in your IDE.
Include "CDetour.h" to your source, and same with the .lib.
The beginning of your code, of your main.cpp file, should look like this:
Next, we'll need to define "ZChatOutput"'s address:Code:#include "Stdafx.h" //Don't complain >.>
#include <windows.h>
#include <CDetour.h> //OR: #include "CDetour.h" if the file is in your projects directory
#pragma comment( lib, "CDetour.lib" )
Alright, that should do it.Code:DWORD dwZChatOutputAddress = 0x0042A230; //Valid for 2007 files
After, you should create a object of the "CDetour" class like so:
Now, our entire "main.cpp" source should look like this:Code:CDetour MyHookLMAO;
Just about done!Code:#include "stdafx.h"
#include <windows.h>
#include <CDetour.h>
#pragma comment( lib, "CDetour.lib" )
DWORD dwZChatOutputAddress = 0x0042A230;
CDetour ZChatOutputDet; //I changed it from "MyHookLMAO" to this for readability.
We'll need to create the thread for ZChatOutput's hook:
Now, whenever ZChatOutput is being used it'll call whatever is in "ZChatOutputHook(...)". Hmm, I'm bored. Getting tired writing this lol. Alright, let's make our hook call a message box. We'll do that like so:Code:void ZChatOutputHook( const char* szMsg, int nType, int nLoc, DWORD dwColor )
{
//.... STUFFS
}
Alright, we're pretty much done, the rest is the main thread and the dll entry point!Code:void ZChatOutputHook( const char* szMsg, int nType, int nLoc, DWORD dwColor )
{
MessageBoxA( NULL, "I just roflbbqsauce", "Title", MB_OK );
ZChatOutputDet.Org( szMsg, nType, nLoc, dwColor );
}
Which is the main thread is done like this:
And the dll entry point is like this:Code:void WINAPI MainThread( void )
{
ZChatOutputDet.Detour( ( PBYTE ) dwZChatOutputAddress, ( PBYTE ) ZChatOutputHook );
ZChatOutputDet.Apply( );
}
We're done! This is what the code should look like as of right now:Code:extern "C" __declspec( dllexport ) BOOL __stdcall DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
DisableThreadLibraryCalls( hInstance );
if( dwReason == DLL_PROCESS_ATTACH )
CreateThread( NULL, NULL, ( LPTHREAD_START_ROUTINE )&MainThread, NULL, NULL, NULL );
else
MessageBoxA( NULL, "Error injecting dll", "Title", MB_OK );
return true;
}
That's all their is to it!Code:#include "stdafx.h"
#include <windows.h>
#include <CDetour.h>
#pragma comment( lib, "CDetour.lib" )
DWORD dwZChatOutputAddress = 0x0042A230;
CDetour ZChatOutputDet;
void ZChatOutputHook( const char* szMsg, int nType, int nLoc, DWORD dwColor )
{
MessageBoxA( NULL, "I just roflbbqsauce", "Title", MB_OK );
ZChatOutputDet.Org( szMsg, nType, nLoc, dwColor );
}
void WINAPI MainThread( void )
{
ZChatOutputDet.Detour( ( PBYTE ) dwZChatOutputAddress, ( PBYTE ) ZChatOutputHook );
ZChatOutputDet.Apply( );
}
extern "C" __declspec( dllexport ) BOOL __stdcall DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
DisableThreadLibraryCalls( hInstance );
if( dwReason == DLL_PROCESS_ATTACH )
CreateThread( NULL, NULL, ( LPTHREAD_START_ROUTINE )&MainThread, NULL, NULL, NULL );
else
MessageBoxA( NULL, "Error injecting dll", "Title", MB_OK );
return true;
}
Now, if I remember right, you can inject this dll and type "/help" (which if I remember right) will execute "ZChatOutput"'s function, thus executing the hook.
Edit-
I attached CDetour with the .lib, and posted an example source
that upon entering the recommended channel, you will be placed in room #1 (or created if none is their) and automatically join.
Clientdll.cpp
ClientDll.hCode:#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include "ClientDll.h"
#include "CDetour.h"
#pragma comment( lib, "CDetour.lib" )
CDetour ZGameClientOnResponseRecommandedChannelDet;
void ZGameClientOnResponseRecommandedChannelHook( MUID* uidChannel )
{
uidCharacter->Low = NULL;
uidCharacter->High = GetMe( );
uidStaged->Low = NULL;
uidStaged->High = GetStage( );
if( uidStaged == NULL )
{
ZPostStageCreate( uidCharacter, "Test Stage", 0, NULL );
uidStaged->Low = NULL;
uidStaged->High = GetStage( );
MSTAGE_SETTING_NODE MStage;
MStage.n1 = NULL;
MStage.n2 = NULL;
MStage.n3 = NULL;
MStage.nGap = NULL;
MStage.nRounds = 65535;
MStage.nMinutes = 65535;
MStage.bLateJoin = true;
MStage.bFriendlyFire = false;
MStage.bMode1 = false;
MStage.bMode2 = false;
MStage.bMode3 = false;
MStage.bMode4 = false;
MStage.bTeamBalance = false;
strcpy_s( MStage.szMapName, "Battle Arena" );
ZPostStageSetting( uidCharacter, uidStaged, MStage );
ZPostStageStart( uidCharacter, uidStaged );
}
ZPostRequestStageJoin( uidCharacter, uidStaged );
ZPostStageEnterBattle( uidCharacter, uidStaged );
ZGameClientOnResponseRecommandedChannelDet.Org( uidChannel );
}
void MainThread( )
{
ZGameClientOnResponseRecommandedChannelDet.Detour( ( PBYTE ) ZGameClientOnResponseRecommandedChannelAddress, ( PBYTE )ZGameClientOnResponseRecommandedChannelHook );
ZGameClientOnResponseRecommandedChannelDet.Apply( );
}
extern "C" __declspec( dllexport ) BOOL __stdcall DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
DisableThreadLibraryCalls( hInstance );
if( dwReason == DLL_PROCESS_ATTACH )
CreateThread( NULL, NULL, ( LPTHREAD_START_ROUTINE )&MainThread, NULL, NULL, NULL );
else
MessageBoxA( NULL, "Error injecting Dll", "ERROR", MB_OK );
return true;
}
Code:unsigned long ZGetGameClientAddress = 0x004ABCC0;
unsigned long ZChatOutputAddress = 0x0042A230;
unsigned long ZGameClientOnResponseRecommandedChannelAddress = 0x00;
unsigned long ZPostStageCreateAddress = 0x00448230;
unsigned long ZPostStageStartAddress = 0x00448E30;
unsigned long ZPostStageSettingAddress = 0x0045BE00;
unsigned long ZPostRequestStageJoinAddress = 0x004257E0;
unsigned long ZPostStageEnterBattleAddress = 0x00;
struct MUID
{
unsigned long Low;
unsigned long High;
};
MUID* uidCharacter = new MUID( );
MUID* uidStaged = new MUID( );
struct MSTAGE_SETTING_NODE
{
int n1;
int n2;
int n3;
char szMapName[32];
char szPlayers;
unsigned int nType;
unsigned int nRounds;
unsigned int nMinutes;
unsigned int nGap;
bool bMode1;
bool bMode2;
bool bMode3;
bool bMode4;
bool bFriendlyFire;
bool bLateJoin;
bool bTeamBalance;
};
typedef DWORD( __cdecl* ZGetGameClientType ) ( );
ZGetGameClientType ZGetGameClient = ( ZGetGameClientType )ZGetGameClientAddress;
//DWORD ZGetGameClient( )
//{
// __asm
// {
// }
//}
//typedef void( __cdecl* ZChatOutputType ) ( const char*, int, int, DWORD );
//ZChatOutputType ZChatOutput = ( ZChatOutputType )ZChatOutputAddress;
void ZChatOutput( const char* szMsg )
{
__asm
{
PUSH 0xFFFFFF
PUSH 0
PUSH 2
PUSH szMsg
CALL ZChatOutputAddress
}
}
//typedef void( __cdecl* ZPostStageCreateType ) ( MUID* uidChar, char* szStageName, bool bPrivate, char* szPassword );
//ZPostStageCreateType ZPostStageCreate = ( ZPostStageCreateType )ZPostStageCreateAddress;
void ZPostStageCreate( MUID* uidChar, char* szStageName, int boolPrivate, char* szPassword )
{
__asm
{
PUSH szPassword
PUSH boolPrivate
PUSH szStageName
PUSH uidChar
CALL ZPostStageCreateAddress
}
}
//typedef void( __cdecl* ZPostRequestStageJoinType ) ( MUID* uidChar, MUID* uidStage );
//ZPostRequestStageJoinType ZPostRequestStageJoin = ( ZPostRequestStageJoinType )ZPostRequestStageJoinAddress;
void ZPostRequestStageJoin( MUID* uidChar, MUID* uidStage )
{
__asm
{
PUSH uidStage
PUSH uidChar
CALL ZPostRequestStageJoin
}
}
//typedef void( __cdecl* ZPostStageStartType ) ( MUID* uidChar, MUID* uidStage );
//ZPostStageStartType ZPostStageStart = ( ZPostStageStartType )ZPostStageStartAddress;
void ZPostStageStart( MUID* uidChar, MUID* uidStage )
{
__asm
{
PUSH uidStage
PUSH uidChar
CALL ZPostStageStartAddress
}
}
//typedef void( __cdecl* ZPostStageSettingType ) ( MUID* uidChar, MUID* uidStage, MSTAGE_SETTING_NODE pSetting );
//ZPostStageSettingType ZPostStageSetting = ( ZPostStageSettingType )ZPostStageSettingAddress;
void ZPostStageSetting( MUID* uidChar, MUID* uidStage, MSTAGE_SETTING_NODE pSetting )
{
__asm
{
PUSH pSetting
PUSH uidStage
PUSH uidChar
CALL ZPostStageSettingAddress
}
}
//typedef void( __cdecl* ZPostStageEnterBattleType ) ( MUID* uidChar, MUID* uidStage );
//ZPostStageEnterBattleType ZPostStageEnterBattle = ( ZPostStageEnterBattleType )ZPostStageEnterBattleAddress;
void ZPostStageEnterBattle( MUID* uidChar, MUID* uidStage )
{
__asm
{
PUSH uidStage
PUSH uidChar
CALL ZPostStageEnterBattleAddress
}
}
unsigned long GetStage( )
{
return *( DWORD* ) ( ZGetGameClient() + 0x1B4 );
}
unsigned long GetMe( )
{
return *( DWORD* ) ( ZGetGameClient() + 0x1A4 );
}
unsigned long GetChannel( )
{
return *( DWORD* ) ( ZGetGameClient() + 0x1AC );
}

