- #include <windows.h>
- #pragma comment(linker, "/ENTRY:main")
- static const unsigned int MAX_ALLOWED_HOOKS = 0x100;
- typedef void(*hook_t)(PCONTEXT);
- typedef ULONG(WINAPI *npvm_t)(HANDLE, PVOID, PULONG, ULONG, PULONG);
- npvm_t NtProtectVirtualMemory;
- bool handler_initialized = false;
- uintptr_t functions_to_hook[MAX_ALLOWED_HOOKS] = { 0 };
- hook_t corresponding_hooks[MAX_ALLOWED_HOOKS] = { (hook_t) 0 };
- uintptr_t reset_hook_location;
- unsigned long HookHandler(PEXCEPTION_POINTERS exc)
- {
- uintptr_t instruction_pointer;
- DWORD hook_length, old_access;
- #ifdef _M_IX86
- instruction_pointer = exc->ContextRecord->Eip;
- #else
- instruction_pointer = exc->ContextRecord->Rip;
- #endif
- if (exc->ExceptionRecord->ExceptionCode != STATUS_ACCESS_VIOLATION && exc->ExceptionRecord->ExceptionCode != STATUS_SINGLE_STEP)
- {
- return (EXCEPTION_CONTINUE_SEARCH);
- }
- else if (exc->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
- {
- hook_length = 1;
- NtProtectVirtualMemory(reinterpret_cast<HANDLE>(~0), &reset_hook_location, &hook_length, PAGE_NOACCESS, &old_access);
- return (EXCEPTION_CONTINUE_EXECUTION);
- }
- for (unsigned int i = 0; i < sizeof(functions_to_hook) / sizeof(uintptr_t); i++)
- {
- if (functions_to_hook[i] == instruction_pointer)
- {
- corresponding_hooks[i](exc->ContextRecord);
- break;
- }
- else if (functions_to_hook[i] == 0)
- {
- break;
- }
- }
- hook_length = 1;
- NtProtectVirtualMemory(reinterpret_cast<HANDLE>(~0), &instruction_pointer, &hook_length, PAGE_EXECUTE, &old_access);
- exc->ContextRecord->EFlags |= 0x100;
- reset_hook_location = instruction_pointer;
- return (EXCEPTION_CONTINUE_EXECUTION);
- }
- bool AddHook(uintptr_t address, hook_t jump)
- {
- DWORD old_access;
- unsigned long hook_length;
- if (!handler_initialized)
- {
- #ifdef __GNUC__
- typedef unsigned long(WINAPI *ADDVEHTYPE)(bool, PVOID);
- ADDVEHTYPE AddVectoredExceptionHandler = (ADDVEHTYPE) GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAddVectoredExceptionHandler");
- AddVectoredExceptionHandler(true, (PVOID) HookHandler);
- #else
- AddVectoredExceptionHandler(true, (PVECTORED_EXCEPTION_HANDLER) HookHandler);
- #endif
- NtProtectVirtualMemory = reinterpret_cast<npvm_t>(GetProcAddress(GetModuleHandle("ntdll.dll"), "NtProtectVirtualMemory"));
- }
- for (unsigned int i = 0; i < sizeof(functions_to_hook) / sizeof(uintptr_t); i++)
- {
- if (functions_to_hook[i] == address)
- {
- return (false);
- }
- else if (functions_to_hook[i] == 0)
- {
- functions_to_hook[i] = (uintptr_t) address;
- corresponding_hooks[i] = (hook_t) jump;
- functions_to_hook[i + 1] = 0;
- corresponding_hooks[i + 1] = reinterpret_cast<hook_t>(0);
- break;
- }
- }
- hook_length = 1;
- NtProtectVirtualMemory(reinterpret_cast<HANDLE>(~0), &address, &hook_length, PAGE_NOACCESS, &old_access);
- return (true);
- }
- bool RemoveHook(uintptr_t address)
- {
- for (unsigned int i = 0; i < sizeof(functions_to_hook) / sizeof(uintptr_t); i++)
- {
- if (functions_to_hook[i] == address)
- {
- functions_to_hook[i] = 0;
- break;
- }
- }
- return (true);
- }
- void myfunc(PCONTEXT ctx)
- {
- *(uintptr_t *)(ctx->Esp + (sizeof(PVOID) << 1)) = (uintptr_t) "Working with arguments is easier than it looks";
- *(uintptr_t *)(ctx->Esp + (sizeof(PVOID) * 3)) = (uintptr_t) "Hooked!";
- }
- int main()
- {
- AddHook((uintptr_t)MessageBoxA, myfunc);
- MessageBoxA(0, "Was I hooked?", "???", 0);
- MessageBoxA(0, "Was I hooked?", "???", 0);
- RemoveHook((uintptr_t)MessageBoxA);
- MessageBoxA(0, "Was I hooked?", "???", 0);
- return (0);
- }
