Thread: FilthyHooker

Results 1 to 9 of 9
  1. #1
    Jason's Avatar
    Join Date
    Apr 2010
    Gender
    male
    Location
    /dev/null
    Posts
    5,704
    Reputation
    918
    Thanks
    7,676
    My Mood
    Mellow

    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.
    Code:
    FilthyHooker *hooker = new FilthyHooker((PBYTE)VTable[42], (PBYTE)&EndsceneHook);
    And here's my EndsceneHook function:
    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;
    }
    or, using my lazyman "SloppySeconds" function:
    Code:
    HRESULT EndsceneHook(IDirect3DDevice9 *pDevice)
    {
        pDevice->Clear(...);
        return hooker->SloppySeconds<HRESULT>(pDevice->Endscene());
    }
    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
    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
    pastie: #3874345 - Pastie

    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);
    }
    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.
    Last edited by Jason; 05-07-2012 at 12:05 PM.

    Quote Originally Posted by Jeremy S. Anderson
    There are only two things to come out of Berkley, Unix and LSD,
    and I don’t think this is a coincidence
    You can win the rat race,
    But you're still nothing but a fucking RAT.


    ++Latest Projects++
    [Open Source] Injection Library
    Simple PE Cipher
    FilthyHooker - Simple Hooking Class
    CLR Injector - Inject .NET dlls with ease
    Simple Injection - An in-depth look
    MPGH's .NET SDK
    eJect - Simple Injector
    Basic PE Explorer (BETA)

  2. The Following 9 Users Say Thank You to Jason For This Useful Post:

    [MPGH]Flengo (02-14-2013),FNV (05-20-2012),Hassan (05-15-2012),pDevice (05-07-2012),stephD (02-02-2016),TokolocoSK (05-08-2012),topblast (05-08-2012),Void (05-07-2012),xhevanlyx (06-06-2014)

  3. #2
    CoderBlack09's Avatar
    Join Date
    Jan 2012
    Gender
    male
    Location
    Visual C++ 2008 Express Editions
    Posts
    769
    Reputation
    10
    Thanks
    62
    My Mood
    Aggressive
    Wow...
    Nice Man,Testing...

  4. #3
    wraithkilla's Avatar
    Join Date
    Apr 2010
    Gender
    male
    Posts
    257
    Reputation
    10
    Thanks
    905
    My Mood
    Busy
    Very Nice

    Thank you for sharing :P

  5. #4
    pDevice's Avatar
    Join Date
    Feb 2012
    Gender
    male
    Location
    d3d9.h
    Posts
    1,306
    Reputation
    15
    Thanks
    420
    My Mood
    Stressed
    Good Job



  6. #5
    Jason's Avatar
    Join Date
    Apr 2010
    Gender
    male
    Location
    /dev/null
    Posts
    5,704
    Reputation
    918
    Thanks
    7,676
    My Mood
    Mellow
    I haven't actually tried this in CA, can someone let me know how it goes?

    Quote Originally Posted by Jeremy S. Anderson
    There are only two things to come out of Berkley, Unix and LSD,
    and I don’t think this is a coincidence
    You can win the rat race,
    But you're still nothing but a fucking RAT.


    ++Latest Projects++
    [Open Source] Injection Library
    Simple PE Cipher
    FilthyHooker - Simple Hooking Class
    CLR Injector - Inject .NET dlls with ease
    Simple Injection - An in-depth look
    MPGH's .NET SDK
    eJect - Simple Injector
    Basic PE Explorer (BETA)

  7. #6
    master131's Avatar
    Join Date
    Apr 2010
    Gender
    male
    Location
    Melbourne, Australia
    Posts
    8,858
    Reputation
    3438
    Thanks
    101,656
    My Mood
    Breezy
    Jason you slut. Nice job.
    Donate:
    BTC: 1GEny3y5tsYfw8E8A45upK6PKVAEcUDNv9


    Handy Tools/Hacks:
    Extreme Injector v3.7.3
    A powerful and advanced injector in a simple GUI.
    Can scramble DLLs on injection making them harder to detect and even make detected hacks work again!

    Minion Since: 13th January 2011
    Moderator Since: 6th May 2011
    Global Moderator Since: 29th April 2012
    Super User/Unknown Since: 23rd July 2013
    'Game Hacking' Team Since: 30th July 2013

    --My Art--
    [Roxas - Pixel Art, WIP]
    [Natsu - Drawn]
    [Natsu - Coloured]


    All drawings are coloured using Photoshop.

    --Gifts--
    [Kyle]

  8. The Following User Says Thank You to master131 For This Useful Post:

    .DLL (05-09-2012)

  9. #7
    Jason's Avatar
    Join Date
    Apr 2010
    Gender
    male
    Location
    /dev/null
    Posts
    5,704
    Reputation
    918
    Thanks
    7,676
    My Mood
    Mellow
    Quote Originally Posted by master131 View Post
    Jason you slut. Nice job.
    icwutudidthar.

    Quote Originally Posted by Jeremy S. Anderson
    There are only two things to come out of Berkley, Unix and LSD,
    and I don’t think this is a coincidence
    You can win the rat race,
    But you're still nothing but a fucking RAT.


    ++Latest Projects++
    [Open Source] Injection Library
    Simple PE Cipher
    FilthyHooker - Simple Hooking Class
    CLR Injector - Inject .NET dlls with ease
    Simple Injection - An in-depth look
    MPGH's .NET SDK
    eJect - Simple Injector
    Basic PE Explorer (BETA)

  10. #8
    sparkart's Avatar
    Join Date
    May 2012
    Gender
    male
    Posts
    15
    Reputation
    10
    Thanks
    1
    I'm curious why you don't use an STL container.

  11. #9
    Jason's Avatar
    Join Date
    Apr 2010
    Gender
    male
    Location
    /dev/null
    Posts
    5,704
    Reputation
    918
    Thanks
    7,676
    My Mood
    Mellow
    Quote Originally Posted by sparkart View Post
    I'm curious why you don't use an STL container.
    'Cos this is more fun. Using vectors would work just as well, or better (for dynamic hooking), but in reality there won't be much difference in memory usage. Access is about the same complexity but I like arrays.
    Last edited by Jason; 05-20-2012 at 02:38 AM.

    Quote Originally Posted by Jeremy S. Anderson
    There are only two things to come out of Berkley, Unix and LSD,
    and I don’t think this is a coincidence
    You can win the rat race,
    But you're still nothing but a fucking RAT.


    ++Latest Projects++
    [Open Source] Injection Library
    Simple PE Cipher
    FilthyHooker - Simple Hooking Class
    CLR Injector - Inject .NET dlls with ease
    Simple Injection - An in-depth look
    MPGH's .NET SDK
    eJect - Simple Injector
    Basic PE Explorer (BETA)