API Function hooking - Easymode
Hello!
Today I will show you how to hook windows API functions the easy way. I made a class to make the process easier and faster. I've succesfully hooked ws2 send and recv functions, loadlibrary in kernel32 and messagebox in user32. As far as I know, you can pretty much hook any API function with the provided code.
Here is the class for hooking (hkClass.h):
Code:
#include <cstdlib>
#include <cstring>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
class ApiCave
{
public:
void GenerateBytes();
void RestoreBytes();
void PlaceJump();
void GetOriginalFuncAddress(char * moduleName, char * functionName);
ApiCave(LPVOID DetourFunction, int iSize);
~ApiCave();
private:
int iInstructionSize;
BYTE *originalBytes, *hookBytes, *tempBytes;
DWORD OriginalFunctionAddress, DetourFunctionAddress, oldprotect;
DWORD myprotect;
};
void ApiCave::GenerateBytes()
{
tempBytes[0] = 0xE9;
tempBytes[5] = 0xC3; // 0xE9 = JMP 0x90 = NOP oxC3 = RET
memcpy(hookBytes, tempBytes, iInstructionSize); // store jmp instruction to JMP
DWORD JMPSize = ((DWORD)DetourFunctionAddress - (DWORD)OriginalFunctionAddress - 5); // calculate jump distance
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, // assign read write protection
myprotect, &oldprotect);
memcpy((LPVOID)originalBytes, (LPVOID)OriginalFunctionAddress, iInstructionSize); // make backup
memcpy(&hookBytes[1], &JMPSize, 4); // fill the nop's with the jump distance (JMP,distance(4bytes),RET)
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, oldprotect, NULL);
}
void ApiCave::RestoreBytes()
{
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, myprotect, &oldprotect);
memcpy((LPVOID)OriginalFunctionAddress, originalBytes, iInstructionSize);
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, oldprotect, NULL);
}
void ApiCave::PlaceJump()
{
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, myprotect, &oldprotect);
memcpy((LPVOID)OriginalFunctionAddress, hookBytes, iInstructionSize);
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, oldprotect, NULL);
}
void ApiCave::GetOriginalFuncAddress(char * moduleName, char * functionName)
{
OriginalFunctionAddress = (DWORD)GetProcAddress(GetModuleHandle(moduleName), functionName);
}
ApiCave::ApiCave(LPVOID DetourFunction, int iSize)
{
iInstructionSize = iSize;
myprotect = PAGE_EXECUTE_READWRITE;
DetourFunctionAddress = (DWORD)DetourFunction;
tempBytes = new BYTE[iSize];
originalBytes = new BYTE[iSize];
hookBytes = new BYTE[iSize];
}
ApiCave::~ApiCave()
{
delete[] tempBytes;
delete[] originalBytes;
delete[] hookBytes;
}
Code:
void ApiCave::GenerateBytes()
{
tempBytes[0] = 0x68; // 68 PUSH
tempBytes[5] = 0xC3; // C3 RETN
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, // assign read write protection
myprotect, &oldprotect);
memcpy((LPVOID)originalBytes, (LPVOID)OriginalFunctionAddress, iInstructionSize); // make backup
memcpy(&hookBytes[1], (DWORD)DetourFunctionAddress, 4); // store the address into tempbytes
VirtualProtect((LPVOID)OriginalFunctionAddress, iInstructionSize, oldprotect, NULL);
}
Lets get started by creating the main.cpp:
Code:
#include "hook.h"
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DoTheHook();
break;
}
return TRUE;
}
Code:
#include "hkClass.h"
int WINAPI MySend(SOCKET, const char *, int, int);
int WINAPI MyMessageBoxA(HWND, LPCTSTR, LPCTSTR, UINT);
ApiCave sendCave((LPVOID)MySend, 6);
ApiCave mbCave((LPVOID)MyMessageBoxA, 6);
int WINAPI MySend (SOCKET s, const char * buf, int len, int flags)
{
sendCave.RestoreBytes();
int retVal = send(s, buf, len, flags);
sendCave.PlaceJump();
return retVal;
}
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR text, LPCTSTR title, UINT type)
{
mbCave.RestoreBytes();
int retVal = MessageBoxA(hWnd, text, title, type);
mbCave.PlaceJump();
return retVal;
}
void DoTheHook()
{
sendCave.GetOriginalFuncAddress("ws2_32.dll", "send");
mbCave.GetOriginalFuncAddress("user32.dll", "MessageBoxA");
sendCave.GenerateBytes();
mbCave.GenerateBytes();
sendCave.PlaceJump();
mbCave.PlaceJump();
}
The stuff that is done in DoTheHook() should be pretty much self explanatory.
And that is it, the functions will now get hooked as soon as the dll is injected into a process. Credits go to wikipedia for an awesome snippet showing the logic behind this. If you have any questions or suggestions, please tell me. Happy coding!
It's simpler and better