FilthyHooker
So I was eating breakfast this morning after about 3 hours sleep last night when an idea struck me about hooking shit. Came home from work and whipped this up. I couldn't decide on what to call it so @Void helped me out and so FilthyHooker was born. It has a bunch of highly inappropriate function names which you can feel free to rename. All I ask is that you leave my name in the source and accredit me whenever you use it, I don't appreciate people who try to steal code and claim it as their own.
What are the benefits of this hook?
Maintains function integrity.
You may have noticed that sometimes when you use a generic hooking method, you crash because the hook ruins the function integrity. Instructions get split halfway through when setting the hook and so the function breaks when you try to call it. My hooking method, however, restores the function to its original state before entering your detour. This means you can call the hooked function like you would normally, and then reset the hook after. It's probably easier to understand if I give you an explanation.
Here's how I create the hook.
And here's my EndsceneHook function:
or, using my lazyman "SloppySeconds" function:
Too easy, there's no chance of your call to IDirect3DDevice9::Endscene breaking because it's exactly the same as it normally is, unhooked and beautiful. You just need to remember to reset the hook at the end of your detour, either manually by calling GiveHerpes() again, or by calling SloppySeconds.
Another good thing about this method of hooking is its encapulation. Everything is stored and managed inside of a class, so you don't need to worry about any of the code behind the hooking, just your own detours.
[TL;DR, gib code]
Here's FilthyHooker.h
pastie: #3874345 - Pastie
And FilthyHooker.cpp
pastie: #3874347 - Pastie
If you guys have any suggestions or comments, feel free to comment on the thread. If you need help just ask; I'll do my best to explain.
What are the benefits of this hook?
Maintains function integrity.
You may have noticed that sometimes when you use a generic hooking method, you crash because the hook ruins the function integrity. Instructions get split halfway through when setting the hook and so the function breaks when you try to call it. My hooking method, however, restores the function to its original state before entering your detour. This means you can call the hooked function like you would normally, and then reset the hook after. It's probably easier to understand if I give you an explanation.
Here's how I create the hook.
Code:
FilthyHooker *hooker = new FilthyHooker((PBYTE)VTable[42], (PBYTE)&EndsceneHook);
Code:
HRESULT EndsceneHook(IDirect3DDevice9 *pDevice)
{
pDevice->Clear(...);
HRESULT hrRealEndscene = pDevice->Endscene(); //See how you can call the original endscene with no worries?
hooker->GiveHerpes(); //reset the hook on Endscene now, so next time it's called we'll hook it again :)
return hrRealEndscene;
}
Code:
HRESULT EndsceneHook(IDirect3DDevice9 *pDevice)
{
pDevice->Clear(...);
return hooker->SloppySeconds<HRESULT>(pDevice->Endscene());
}
Another good thing about this method of hooking is its encapulation. Everything is stored and managed inside of a class, so you don't need to worry about any of the code behind the hooking, just your own detours.
[TL;DR, gib code]
Here's FilthyHooker.h
Code:
/*
FilthyHooker class written by Jason.
Feel free to use this class however you please, I take no responsibility for how you use it, though.
You are welcome to use the class, all I ask is that you leave this message at the top, and give credit
where it's due.
*/
#ifndef FILTHYHOOKER_H
#define FILTHYHOOKER_H
#include <Windows.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#define SZ_HOOK 0x000A //the size of the hook, don't fucking touch this or I will bang your mum.
#define N_HOOKS 0x00FF //maximum number of hooks at any one time, if you're really hooking more than 255 functions at once, you have a sad, sad addiction and should seek help, or just change the definition :3
//normalize the buffer so I don't have to keep creating SZ_HOOK sized BYTE buffers everywhere; it's boring.
typedef struct _hbuff
{
BYTE value[SZ_HOOK];
} HOOK_BUFFER, *PHOOK_BUFFER;
//structure to hold information about a particular hook.
typedef struct _hinfo : HOOK_BUFFER
{
PBYTE function;
PBYTE detour;
} HOOK_INFO, *PHOOK_INFO;
class FilthyHooker
{
private:
//static vars for out-of-class access.
static HOOK_INFO hooks[N_HOOKS];
static DWORD ref;
//couple of members, just the unique stub and the index for this instance.
DWORD index;
HOOK_BUFFER stub;
//repatch the original function back to its former glory, returns the address of the detour corresponding to the function.
static PBYTE Repatch(int id);
//little stubby bastard to allow for function repatching before handing over control to the user's detour.
static void Proxy(int id);
public:
//Construct a new hook, redirecting pFunction to pDetour.
FilthyHooker(PBYTE pFunction, PBYTE pDetour);
//destroy.
~FilthyHooker(void);
//check if the hook is set
BOOL HasAids(void);
//Set the hook.
void GiveHerpes(void);
//Unset the hook.
void SeeDoctor(void);
//purely a lazymans function. Just resets the hook on the function and then returns the param you gave it.
//It's nice when you just want to return the original function's value, then reset the hook, i.e for an Endscene hook (pDevice = IDirect3DDevice9*, pHook = JHook*)
//return pHook->SloppySeconds<HRESULT>(pDevice->Endscene());
//resets the hook and returns the value all at once. Easy as.
template <class T>
T SloppySeconds(T retval)
{
this->GiveHerpes();
return reval;
}
};
#endif
And FilthyHooker.cpp
Code:
#include "FilthyHooker.h"
//just a couple of simple pointer arithmetic macros.
#define AddPtr(t,p1,p2) (t)((ULONG_PTR)(p1) + (ULONG_PTR)(p2))
#define SubPtr(t,p1,p2) (t)((ULONG_PTR)(p1) - (ULONG_PTR)(p2))
//copy an existing HOOK_BUFFER into another.
#define CopyBuffer(p1, p2) (*(PHOOK_BUFFER)(p1) = *(PHOOK_BUFFER)(p2))
//same as CopyBuffer but with memory protection to allow writing as well.
#define SafeCopyBuffer(p1, p2) DWORD d1, d2; VirtualProtect(p1, SZ_HOOK, PAGE_EXECUTE_READWRITE, &d1); CopyBuffer(p1, p2); VirtualProtect(p1, SZ_HOOK, d1, &d2)
//static initializer list.
DWORD FilthyHooker::ref = 0;
HOOK_INFO FilthyHooker::hooks[N_HOOKS];
FilthyHooker::FilthyHooker(PBYTE pFunction, PBYTE pDetour)
{
this->index = FilthyHooker::ref++;
//check if the max number of hooks has been overrun. Basically this isn't my fault if it does happen
//so fuck you; I'll half ass my error checking. Basically just piss around and do nothing if there's too many hooks.
if (this->index < N_HOOKS)
{
//create the assembler stub for the hook. Cbf using my HOOK_BUFFER struct, too much dereferencing hurts my head.
BYTE bStub[SZ_HOOK] = { 0x68, 0xC3, 0xE1, 0xCC, 0xCC, 0xE9, 0x90, 0x32, 0xFF, 0xE9 };
//start building the hook info struct.
HOOK_INFO *pHook = &FilthyHooker::hooks[this->index];
pHook->detour = pDetour;
pHook->function = pFunction;
//patching
*(DWORD*)(&bStub[1]) = this->index;
*(DWORD*)(&bStub[6]) = SubPtr(DWORD, &Proxy, AddPtr(DWORD, pHook->function, SZ_HOOK));
CopyBuffer(&this->stub, bStub); //create our internal copy of the assembler stub.
CopyBuffer(pHook, pHook->function); //backup the functions prologue code.
//set the hook.
this->GiveHerpes();
}
}
//destructor? pfft, half this class is static anyway. Just unhook and that's about that.
FilthyHooker::~FilthyHooker(void)
{
this->SeeDoctor();
}
inline
BOOL FilthyHooker::HasAids(void)
{
//very straightforward, test to see if the hook is set by comparing bytes.
BOOL same = TRUE;
HOOK_INFO pHook = FilthyHooker::hooks[this->index];
for(DWORD i = 0; i < SZ_HOOK && same; i++)
same = (pHook.function[i] == this->stub.value[i]);
return same;
}
inline
PBYTE FilthyHooker::Repatch(int id)
{
//restore the original function's prologue code so that it works again.
HOOK_INFO *pHook = &FilthyHooker::hooks[id];
SafeCopyBuffer(pHook->function, pHook);
return pHook->detour;
}
__declspec(naked) void FilthyHooker::Proxy(int id)
{
//I'm lazy so I split 'Repatch' and this function into two seperate functions to avoid actually having
//to think about stack offsets in too much detail. Turns out it was rather handy in that I could just
//write the Unhook as a public wrapper for Repatch. Winner?
__asm
{
push [esp]; //push id back onto the stack.
call Repatch; //call the repatch function.
add esp, 8; //clean
jmp eax; //call the user-defined detour.
}
}
void FilthyHooker::GiveHerpes(void)
{
if (this->index < N_HOOKS && !this->HasAids())
{
HOOK_INFO *pHook = &FilthyHooker::hooks[this->index];
SafeCopyBuffer(pHook->function, &this->stub);
}
}
void FilthyHooker::SeeDoctor(void)
{
//As I mentioned before, by splitting Repatch and Proxy into 2 seperate functions I had to do zero work
//with this function. I call awesome.
if (this->index < N_HOOKS && this->HasAids())
FilthyHooker::Repatch(this->index);
}
If you guys have any suggestions or comments, feel free to comment on the thread. If you need help just ask; I'll do my best to explain.


