#pragma once #define WIN32_LEAN_AND_MEAN #include #include #include void Patch(DWORD vOffset, const LPVOID mem, UINT len); template inline void Patch(DWORD vOffset, Type value) { Patch(vOffset, &value, sizeof(Type)); } void PatchBytes(DWORD vOffset, std::initializer_list bytes); void Nop(DWORD vOffset, UINT len); inline void ReadWriteProtect(DWORD location, DWORD size) { DWORD _; VirtualProtect((PVOID) location, size, PAGE_EXECUTE_READWRITE, &_); } template Func SetRelPointer(DWORD location, Func hookFunc) { // Set and calculate the relative offset for the hook function DWORD& relOriginalLocation = GetValue(location); DWORD originalPointer = location + relOriginalLocation + 4; DWORD hookFuncLocation = *((PDWORD) &hookFunc); relOriginalLocation = hookFuncLocation - (location + 4); return GetFuncDef(originalPointer); } template void Hook(DWORD location, Func hookFunc, UINT instrLen, bool jmp = false) { assert(instrLen >= 5); // Set the opcode for the call or jmp instruction Patch(location, jmp ? 0xE9 : 0xE8); // 0xE9 = jmp, 0xE8 = call // Set the relative address SetRelPointer(location + 1, hookFunc); // Nop out excess bytes if (instrLen > 5) Nop(location + 5, instrLen - 5); } template Func Trampoline(DWORD location, Func hookFunc, UINT instrLen) { // Allocate memory for gateway function. PBYTE gatewayFunc = (PBYTE) VirtualAlloc(nullptr, instrLen + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Copy the instruction(s) that will be overwritten by setting the hooks to the gateway code. ReadWriteProtect(location, instrLen); memcpy(gatewayFunc, (PVOID) location, instrLen); // Jmp from location to hook function. Hook(location, hookFunc, instrLen, true); // Jmp from gateway to original function. Hook((DWORD) (gatewayFunc + instrLen), GetFuncDef(location + instrLen), 5, true); // Return handle for calling the gateway function which in turn calls the original function. return GetFuncDef((DWORD) gatewayFunc); } template void CleanupTrampoline(Func trampolineFunc) { VirtualFree((LPVOID) *((PDWORD) &trampolineFunc), 0, MEM_RELEASE); } template Func SetPointer(DWORD location, Func hookFunc) { DWORD originalPointer = GetValue(location); *(Func*) location = hookFunc; return GetFuncDef(originalPointer); } template inline Type& GetValue(DWORD location) { ReadWriteProtect(location, sizeof(Type)); return *(Type*) location; } template inline Func GetFuncDef(DWORD funcAddr) { return *(Func*) &funcAddr; } DWORD GetUnloadedModuleHandle(LPCTSTR moduleName); struct NopStr { UINT len; LPCSTR nopSequence; };