All pastes #258120 Raw Edit

Unnamed

public text v1 · immutable
#258120 ·published 2006-11-26 03:58 UTC
rendered paste body
#pragma once

#include <windows.h>
#include <stdio.h>

namespace RITZ
{
	template<typename FUNCTIONTYPE>
	class HOOK
	{
	public:
		const static int PATCH_LEN = 5;

		void Hook(FUNCTIONTYPE from, FUNCTIONTYPE to, HMODULE hmod = GetCurrentModule())
		{
			SafeMemcpy(overwritten, from, PATCH_LEN); // Save original function code

			static BYTE jumpcode[] = {0xE9, 0,0,0,0}; // Offset jump code
			*((DWORD*)(jumpcode+1)) = (DWORD)to - (DWORD)from - PATCH_LEN; // Write in jump operand

			SafeMemcpy(from, jumpcode, PATCH_LEN); // Insert hook

			orig = from;
			hook = to;
			this->hmod = hmod;
			hooked = true;
		}

		void Hook(char *from_name, FUNCTIONTYPE to, HMODULE hmod = GetCurrentModule())
		{
			FARPROC procaddr = GetProcAddress(hmod, from_name);
			if(procaddr)
			{
				Hook((FUNCTIONTYPE)procaddr, to, hmod);
			}
		}

		void Unhook()
		{
			SafeMemcpy(orig, overwritten, PATCH_LEN);
			hooked = false;
		}

		void Rehook()
		{
			Hook(orig, hook, this->hmod);
		}

		FUNCTIONTYPE orig; // For calling after unhooking.
		FUNCTIONTYPE hook;

	private:
		BYTE overwritten[PATCH_LEN];
		HMODULE hmod;
		bool hooked;
		
		void SafeMemcpy(void *to, void *from, DWORD size)
		{
			DWORD oldprot_from;
			DWORD oldprot_to;

			VirtualProtect(from, 8, PAGE_EXECUTE_READWRITE, &oldprot_from);
			VirtualProtect(to, 8, PAGE_EXECUTE_READWRITE, &oldprot_to);

			__int64 todata = *((__int64*)to);
			__int64 fromdata = *((__int64*)from);

			// So that we don't overwrite more than 'size',
			// copy the data that we are supposed to keep to the 'fromdata' buffer.
			memcpy(((BYTE*)&fromdata)+size, ((BYTE*)&todata)+size, 8-size);

			__asm
			{
				mov edx, dword ptr ds:[todata+4]
				mov eax, dword ptr ds:[todata]

				mov ecx, dword ptr ds:[fromdata+4]
				mov ebx, dword ptr ds:[fromdata]

				mov esi, to // Load to address into register for cmpxchg8b.
				lock cmpxchg8b qword ptr ds:[esi] // Write
			}

			VirtualProtect(from, 8, oldprot_from, &oldprot_from);
			VirtualProtect(to, 8, oldprot_from, &oldprot_to);
		}

		static HMODULE GetCurrentModule()
		{
			MEMORY_BASIC_INFORMATION mbi;
			static int dummy;
			VirtualQuery(&dummy, &mbi, sizeof(mbi));

			return (HMODULE)mbi.AllocationBase;
		}

	public:
		HOOK()
		{
			hooked = false;
		}

		HOOK(FUNCTIONTYPE from, FUNCTIONTYPE to, HMODULE hmod)
		{
			Hook(from, to, hmod);
		}

		~HOOK()
		{
			if(hooked)
				Unhook();
		}
	};
}