Skip to content
MPGHThe Dark Arts
/
RegisterLog in
Forum
Community
What's NewLatest posts across the boardTrendingHottest threads right nowSubscribedThreads you follow
Discussion
GeneralIntroductionsEntertainmentDebate FortFlaming & Rage
Board
News & AnnouncementsMPGH TimesSuggestions & HelpGiveaways
More Sections
Art & Graphic DesignProgrammingHackingCryptocurrency
Hacks & Cheats
Games
ValorantCS2 / CS:GOCall of Duty / WarzoneFortniteApex LegendsEscape From Tarkov
+14 moreLeague of LegendsGTA VMinecraftRustROTMGBattlefieldTroveBattleOnCombat ArmsCrossFireBlackshotRuneScapeDayZDead by Daylight
Resources
Game Hacking TutorialsReverse EngineeringGeneral Game HackingAnti-CheatConsole Game Hacking
Tools
Game Hacking ToolsTrainers & CheatsHack/Release NewsNew
Submit a release →Share your cheat, tool, or config with the community.
AINEW
AI Tools
General & DiscussionPrompt EngineeringLLM JailbreaksHotAI Agents & AutomationLocal / Open Models
AI × Gaming
AI Aimbots & VisionML Anti-CheatGame Bots & Automation
Create
AI Coding / Vibe CodingAI Art & MediaAI Voice & TTS
The AI frontier →Where game hacking meets modern machine learning. Jump in.
Marketplace
Buy & Sell
SellingBuyingTradingUser Services
Trust & Safety
Middleman LoungeMarketplace TalkVouch Copy Profiles
Money
Cryptocurrency TalkCurrency ExchangeWork & Job Offers
Start selling →List accounts, services, and goods. Use the middleman to trade safe.
MPGH The Dark Arts

A community for offensive security research, reverse engineering, and AI.

Community

ForumMarketplaceSearch

Account

RegisterLog in

Legal

Privacy PolicyForum RulesHelp & FAQ
© 2026 MPGH · All rights reserved.Built by the community, for the community. For educational purposes onlyContent is shared for security research and education — we don't condone illegal use. You're responsible for complying with applicable laws. Use at your own risk.
Home › Forum › MultiPlayer Game Hacks & Cheats › Combat Arms Hacks & Cheats › Combat Arms Hack Coding / Programming / Source Code › FilthyHooker

FilthyHooker

Posts 1–9 of 9 · Page 1 of 1
Jason
Jason
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.
#1 · edited 14y ago · 14y ago
CO
CoderBlack09
Wow...
Nice Man,Testing...
#2 · 14y ago
wraithkilla
wraithkilla
Very Nice

Thank you for sharing :P
#3 · 14y ago
pDevice
pDevice
Good Job
#4 · 14y ago
Jason
Jason
I haven't actually tried this in CA, can someone let me know how it goes?
#5 · 14y ago
master131
[MPGH]master131
Jason you slut. Nice job.
#6 · 14y ago
Jason
Jason
Quote Originally Posted by master131 View Post
Jason you slut. Nice job.
icwutudidthar.
#7 · 14y ago
SP
sparkart
I'm curious why you don't use an STL container.
#8 · 14y ago
Jason
Jason
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.
#9 · edited 14y ago · 14y ago
Posts 1–9 of 9 · Page 1 of 1

Post a Reply

Tags for this Thread

None