Hooking via Vectored Exception Handling

In computer programming, the term hooking covers a range of techniques used to alter or augment the behaviour of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a hook.

Hooking is used for many purposes, including debugging and extending functionality. Examples might include intercepting keyboard or mouse event messages before they reach an application, or intercepting operating system calls in order to monitor behavior or modify the function of an application or other component. It is also widely used in benchmarking programs, for example frame rate measuring in 3D games, where the output and input is done through hooking.

Hooking can also be used by malicious code. For example, rootkits, pieces of software that try to make themselves invisible by faking the output of API calls that would otherwise reveal their existence, often use hooking techniques.

https://en.wikipedia.org/wiki/Hooking

Hooking Methods

The content of this section came from UC and is not my own words. Kindly visit the page for more detailed and complete info.

Byte patching (.text section)

Execute-Speed: 10
Skill-Level: 2
Detectionrate: 5 – 7

Byte patching in the .text section is the easiest and most common way to place a hook.
Hooking libraries like Microsoft Detours (Download) are used alot.
Some anticheats are still retarded and dont even scan the .text section, but most of them figured out that one finally.
There are various ways to redirect the code flow. You can place a normal JMP instruction (5 bytes in size) or try some hotpatching using a short JMP (2 bytes in size) to some location where is more space for a 5 byte JMP.
You can place a CALL instruction which works same as a JMP but pushes the returnaddress on the stack before jumping. You can also just push the address on the stack and then call RETN which jumps to the last adddress on stack and therefore behaves like a JMP.
Most anticheats figured that out and scan for those byte sequences.

IAT/EAT Hooking

Execute-Speed: 10
Skill-Level: 3
Detectionrate: 5

This hooking method is based on how the PE files are working on windows.
It means “Import/Export Address Table”. This address table contains the pointer to the APIs and is adjusted by the PE loader when the file is executed.
You can either loop the whole table and search for a function and redirect it or you can find it manually using OllyDbg or IDA.
The basic idea is that you replace a certain API with your hooked function.
Thats not only good for simple API hooking but it can also be used for a DirectX hook: http://www.unknowncheats.me/forum/d3…ok-any-os.html

VMT Hooking / Pointer redirections

Execute-Speed: 10
Skill-Level: 3 – 5
Detectionrate: 3

One of the best hooking methods because there is no API or basic way to detect those hooks.
Most anticheats detect VMT hooks on the D3D-Device of the engine but thats not what we want to do anyways.
Nearly every engine has an internal rendering class which can be hooked. You can for example just hook Endscene using detours and log the returnaddress.
When you check the code at the returnaddress you will find the function which calls Endscene. Now search for references to this function and reverse a bit, you will mostlikely get a pointer in the .data section which represents a virtual table.
Those tables just contain addresses of functions and can be easily replaced even without the usage of VirtualProtect because .data has normally Read/Write flags.

HWBP Hooking

Execute-Speed: 6
Skill-Level: 6
Detectionrate: 4

We already talked earlier about hardware breakpoints but this time we wont change any bytes in the .text section.
Like I said earlier you also have to place an exception handler to catch the exception!
They can be placed for each thread individually but that also means we NEED the handle of the thread.
Some anticheats hide all threads using rootkit techniques, but that doesnt mean we cant get into the thread!

PageGuard Hooking

Execute-Speed: 1
Skill-Level: 8
Detectionrate: 1

PageGuard hooks are really stealthy, nearly no AntiCheat detects them. This was detected for GameGuard but only in the game, it worked perfectly on the GameGuard file itself.
Undetected for HackShield, XignCode, Punkbuster, and more. This method can be compared to a HWBP hook. First you have to register an exception handler.
Then you have to trigger the exception, this time by marking the complete memory page with PAGE_GUARD using VirtualProtect, which will result in an exception.
When you read about PAGE_GUARD on msdn you will find out that its removed automaticly after the first exception occured.
In our exception handler we now set the single step flag and single step all instructions until we hit the address we looked for.
We can change the EIP again like we did earlier, but now we have to mark the page as PAGE_GUARD again otherwise the hook wont be triggered again!
This hooking method is slow as hell due to the usage of the single step flag and should only be used for functions which get called very rarely.

Forced Exception hooking

Execute-Speed: 5
Skill-Level: 8
Detectionrate: 2

You can force exceptions in a program by manipulating pointers and stored values.
For example you can grab the device pointer of a game and set it to null, then wait in your exception handler until the program throws an exception.
The exception itself should be a null-pointer dereference, just do your stuff in the redirected EIP hook and then reset the original values and continue the execution.
Since the pointer is now fine again it will execute until you set the pointer to null again. There are many more ways to use this but since I used that method before I know this works forreal.
You might need alot of work to fix all the exceptions which requires some skills.
Heres an example on forcing an exception: http://www.unknowncheats.me/forum/c-…struction.html

VEH Hooking (Let’s get our hands dirty!)

But why VEH? It’s slow AF. Yes it’s slow but I would not take risk byte-patching because it is prone for integrity check which may result to your account being banned. Also, other methods are not applicable such as IAT and VMT. And my last resort is VEH hooking.

Well, your choice will be dependent to situation, every methods has pros and cons. Its up to you on how you would utilize the information.

Implementation

Implementation is quite easy! Thanks to many samples out there!

LONG WINAPI Handler(EXCEPTION_POINTERS* pExceptionInfo)
{
	
	if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) //We will catch PAGE_GUARD Violation
	{
		if (pExceptionInfo->ContextRecord->XIP == (DWORD)og_fun) //Make sure we are at the address we want within the page
		{
			pExceptionInfo->ContextRecord->XIP = (DWORD)hk_fun; //Modify EIP/RIP to where we want to jump to instead of the original function
		}

		pExceptionInfo->ContextRecord->EFlags |= 0x100; //Will trigger an STATUS_SINGLE_STEP exception right after the next instruction get executed. In short, we come right back into this exception handler 1 instruction later
		return EXCEPTION_CONTINUE_EXECUTION; //Continue to next instruction
	}

	if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) //We will also catch STATUS_SINGLE_STEP, meaning we just had a PAGE_GUARD violation
	{
		//uint32_t dwOld;
		//dwOld = Controller->VirtualProtect((DWORD)og_fun, 1, PAGE_EXECUTE_READ | PAGE_GUARD); //Reapply the PAGE_GUARD flag because everytime it is triggered, it get removes

		DWORD dwOld;
		auto addr = (PVOID)og_fun;
		auto size = (SIZE_T)((int)1);
		NTSTATUS res = makesyscall<NTSTATUS>(0x50, 0x00, 0x00, 0x00, "RtlInterlockedCompareExchange64", 0x170, 0xC2, 0x14, 0x00)(GetCurrentProcess(), &addr, &size, PAGE_EXECUTE_READ | PAGE_GUARD, &dwOld);

		return EXCEPTION_CONTINUE_EXECUTION; //Continue the next instruction
	}

	return EXCEPTION_CONTINUE_SEARCH; //Keep going down the exception handling list to find the right handler IF it is not PAGE_GUARD nor SINGLE_STEP
}
bool AreInSamePage(const DWORD* Addr1, const DWORD* Addr2)
{
	MEMORY_BASIC_INFORMATION mbi1;
	if (!VirtualQuery(Addr1, &mbi1, sizeof(mbi1))) //Get Page information for Addr1
		return true;

	MEMORY_BASIC_INFORMATION mbi2;
	if (!VirtualQuery(Addr2, &mbi2, sizeof(mbi2))) //Get Page information for Addr1
		return true;

	if (mbi1.BaseAddress == mbi2.BaseAddress) //See if the two pages start at the same Base Address
		return true; //Both addresses are in the same page, abort hooking!

	return false;
}
bool Hook(DWORD original_fun, DWORD hooked_fun)
{
	og_fun = original_fun;
	hk_fun = hooked_fun;

	//We cannot hook two functions in the same page, because we will cause an infinite callback
	if (AreInSamePage((const DWORD*)og_fun, (const DWORD*)hk_fun))
		return false;

	//Register the Custom Exception Handler
	VEH_Handle = AddVectoredExceptionHandler(true, (PVECTORED_EXCEPTION_HANDLER)LeoHandler);

	//Toggle PAGE_GUARD flag on the page
	if (VEH_Handle) {
		auto addr = (PVOID)og_fun;
		auto size = (SIZE_T)((int)1);

		if (NT_SUCCESS(makesyscall<NTSTATUS>(0x50, 0x00, 0x00, 0x00, "RtlInterlockedCompareExchange64", 0x170, 0xC2, 0x14, 0x00)(GetCurrentProcess(), &addr, &size, PAGE_EXECUTE_READ | PAGE_GUARD, &oldProtection))) {
			return true;
		}

	}
	return false;
}

POC

I hooked a function in a game that is executed every character’s action.

Conclusion

VEH is quite simple to implement, but again, it might depend on the situation you are working on. Besides, you will feel the impact on decreased performance because this is quite slow unlike other methods.

Thank you so much for reading this. I hope you enjoyed this writeup!

Leave a Reply

Your email address will not be published. Required fields are marked *