SolvedAPI Hooking

Posts 1–6 of 6 · Page 1 of 1
API Hooking
I built a class for hooking API's, but it's not working as excepted.
If you wanna look at it, here's the code (APIHook::HookFunction isn't working properly when called):


 
Code in APIHook.h / APIHook.c

Code:
	template <class T> static bool MemoryTools::WriteMemory(void* pAddress, T tValue){

		if (pAddress && IsReadableMemory(pAddress)){
			DWORD dwOldProtect = 0;

			if (VirtualProtect(pAddress, sizeof(T), PAGE_READWRITE, &dwOldProtect))
			{
				*(T*)pAddress = tValue;

				if (dwOldProtect != PAGE_READWRITE)
					VirtualProtect(pAddress, sizeof(T), dwOldProtect, &dwOldProtect);

				return true;
			}
		}

		return false;
	}

//struct for handling API hooks
struct APIHookInfo{
		unsigned long id;
		PVOID pTarget;					//api to be hooked;
		PVOID pTrampoline;				//trampoline for our API;
		PVOID pDetour;					//detour function;
		unsigned long dwBackupSize;		//size of overritten data;
		BYTE  IPs[0x10];				//overritten data;

		APIHookInfo(){
			static unsigned long nextid = 0;

			id = ++nextid;
			pTarget = pTrampoline = pDetour = nullptr;
			dwBackupSize = NULL;
			memset(IPs, 0, 0x10);
		}

		bool operator == (APIHookInfo i){
			return (this->id == i.id);
		}
	};
#define MakePtr(ptr1, ptr2, type) (type)((DWORD_PTR)ptr1 + (DWORD_PTR)ptr2)
#define MakeDelta(ptr1, ptr2, type) (type)((DWORD_PTR)ptr1 - (DWORD_PTR)ptr2)


unsigned long APIHook::GetInstructionSize(PVOID lpInstruction){ //this function uses hde32 / hde64
	if (lpInstruction && MemoryTools::IsReadableMemory(lpInstruction)){
		hde_struct e = hde_struct();
		return hde_disasm(lpInstruction, &e);
	}
	return 0;
}

PVOID APIHook::HookFunction(APIHook::APIHookInfo i){
	PauseThreads();

	DWORD dwOldProtect = 0;															//Used for virtual protection.

	if (i.dwBackupSize == NULL){
		while (i.dwBackupSize < 5){
			i.dwBackupSize += GetInstructionSize(MakePtr(i.pTarget, i.dwBackupSize, PVOID));
		}
	}


	i.pTrampoline = new BYTE[i.dwBackupSize + 6]; //backup + jmp size + retn


	VirtualProtect(i.pTarget, i.dwBackupSize, PAGE_READWRITE, &dwOldProtect);
	
	memcpy(i.pTrampoline, i.pTarget,
		i.dwBackupSize);

	memcpy(i.IPs, i.pTarget,
		i.dwBackupSize);

	memset(i.pTarget, 0x90, i.dwBackupSize); //memset function

	MemoryTools::WriteMemory<BYTE>(i.pTarget, 0xE9); //0xE9 (opcode for relative jmp)
	MemoryTools::WriteMemory<DWORD>(MakePtr(i.pTarget, 1, PVOID), (unsigned long)i.pDetour - (unsigned long)i.pTarget - 5); //Sets the offset

	VirtualProtect(i.pTarget, i.dwBackupSize, dwOldProtect, &dwOldProtect);

	MemoryTools::WriteMemory<BYTE>(MakePtr(i.pTrampoline, i.dwBackupSize, PVOID), 0xE9);
	MemoryTools::WriteMemory<DWORD>(MakePtr(i.pTrampoline, i.dwBackupSize + 1, PVOID), 
(unsigned long)i.pTarget - (unsigned long)i.pTrampoline - 5);

	MemoryTools::WriteMemory<BYTE>(MakePtr(i.pTrampoline, i.dwBackupSize + 5, PVOID), 0xC3);

	FlushInstructionCache(GetCurrentProcess(), 0, 0);

	hookList.push_back(i); //adds this hook to the "hook" list

	ResumeThreads();
	return i.pTrampoline;

}
PVOID APIHook::UnhookFunction(APIHook::APIHookInfo i){
	PauseThreads();
	DWORD dwOldProtect = 0;															//Used for virtual protection.

	if (i.dwBackupSize == NULL){
		while (i.dwBackupSize < 5){
			i.dwBackupSize += GetInstructionSize(MakePtr(i.pTarget, i.dwBackupSize, PVOID));
		}
	}

	VirtualProtect(i.pTarget, i.dwBackupSize, PAGE_READWRITE, &dwOldProtect);

	memcpy(i.pTarget, i.IPs, i.dwBackupSize);

	VirtualProtect(i.pTarget, i.dwBackupSize, dwOldProtect, &dwOldProtect);

	delete i.pTrampoline;

	FlushInstructionCache(GetCurrentProcess(), 0, 0);
	ResumeThreads();

	for (std::vector<APIHookInfo>::iterator a = hookList.begin(); a < hookList.end(); a++){
		if (*a == i){
			hookList.erase(a);
			break;
		}
	}


	return i.pTarget;
}

PVOID APIHook::HookFunction(PVOID lpFunction, PVOID lpDetourFunction){
	APIHookInfo i = APIHookInfo();
	i.pTarget = lpFunction;
	i.pDetour = lpDetourFunction;
	return HookFunction(i);
}
PVOID APIHook::UnhookFunction(PVOID lpFunction){
	for (auto &i : hookList){
		if (i.pTarget == lpFunction) return UnhookFunction(i);
	}

	return nullptr;
}

I am pretty much asleep but your issue is mostly because of miscalucaltions in the addies (at least that's where I think most people might have lapsuses). Refer to this article in order to better understand how "manual" hooking should be done:
http://www.codeproject.com/Articles/...ith-MS-Detours

Pretty much you calculate the distance from your target function to the detour function minus 5. Additionally you simply build up a jump instruction which jumps from that point to your detour function. Needless to say this might totally replace the original function. So in order to truly hook the function every time that you install the hook after the function is called you gotta unhook it and call the original function again. This can be a pain in the butt.

In addition (as the article explains) why don't you use detours? They're easy and pretty efficient. (A presumable answer would be "I love making my own algorithms", at least that's what I would say )
Quote Originally Posted by user590177 View Post
I am pretty much asleep but your issue is mostly because of miscalucaltions in the addies (at least that's where I think most people might have lapsuses). Refer to this article in order to better understand how "manual" hooking should be done:
http://www.codeproject.com/Articles/...ith-MS-Detoursⓘ

Pretty much you calculate the distance from your target function to the detour function minus 5. Additionally you simply build up a jump instruction which jumps from that point to your detour function. Needless to say this might totally replace the original function. So in order to truly hook the function every time that you install the hook after the function is called you gotta unhook it and call the original function again. This can be a pain in the butt.

In addition (as the article explains) why don't you use detours? They're easy and pretty efficient. (A presumable answer would be "I love making my own algorithms", at least that's what I would say )
I love making my own algorithms.

And I'm using this on a program that checks the calls to those functions, meaning I can either spoof the return address, or make my own algorithms. And the latter seems to be faster (at least that's what I initially thought).
Quote Originally Posted by R3DDOT View Post


I love making my own algorithms.

And I'm using this on a program that checks the calls to those functions, meaning I can either spoof the return address, or make my own algorithms. And the latter seems to be faster (at least that's what I initially thought).
An answer would be save the backed up funcion somewhere in the memory and after calling the hooked jump back to the original.
Another great help would be to specify what's going wrong
Quote Originally Posted by user590177 View Post


An answer would be save the backed up funcion somewhere in the memory and after calling the hooked jump back to the original.
Another great help would be to specify what's going wrong
My bad, I thought I had commented the function.

API Hooking functions like this:

When hooking a API, we need 3 functions. We need the target function (API we want to hook), our detour function (our hook) and a "trampoline" (executes the original function by simulating the overritten opcodes then jumping back to the original function, skipping the hook).

This causes an exception of std::bad_alloc, but I don't see where I might be allocating too much memory.


- - - Updated - - -

Fixed it. I modified the post above with the fixed version, feel free to use. @Mayion
Great to know you fixed your problem by yourself, good job.
Posts 1–6 of 6 · Page 1 of 1
This thread is closed for replies.

Similar Threads

Tags for this Thread

None

Talk with us