77 lines
2.3 KiB
C++
77 lines
2.3 KiB
C++
#pragma once
|
|
|
|
#include <windows.h>
|
|
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <initializer_list>
|
|
|
|
namespace rem
|
|
{
|
|
void Patch(DWORD address, const void* data, UINT length);
|
|
void PatchBytes(DWORD address, std::initializer_list<BYTE> bytes);
|
|
void Nop(DWORD address, UINT length);
|
|
void ReadWriteProtect(DWORD address, DWORD size);
|
|
|
|
template <typename Type>
|
|
inline void Patch(DWORD address, Type value)
|
|
{
|
|
Patch(address, &value, sizeof(Type));
|
|
}
|
|
|
|
template <typename Type>
|
|
inline Type& ValueAt(DWORD address)
|
|
{
|
|
ReadWriteProtect(address, sizeof(Type));
|
|
return *reinterpret_cast<Type*>(address);
|
|
}
|
|
|
|
template <typename Func>
|
|
inline Func FunctionAt(DWORD address)
|
|
{
|
|
return reinterpret_cast<Func>(address);
|
|
}
|
|
|
|
template <typename Func>
|
|
Func SetRelPointer(DWORD location, Func hook)
|
|
{
|
|
DWORD& relative = ValueAt<DWORD>(location);
|
|
DWORD original = location + relative + 4;
|
|
DWORD hookAddress = *reinterpret_cast<DWORD*>(&hook);
|
|
relative = hookAddress - (location + 4);
|
|
return FunctionAt<Func>(original);
|
|
}
|
|
|
|
template <typename Func>
|
|
void Hook(DWORD address, Func hook, UINT instructionLength, bool jump = false)
|
|
{
|
|
assert(instructionLength >= 5);
|
|
Patch<BYTE>(address, jump ? 0xE9 : 0xE8);
|
|
SetRelPointer(address + 1, hook);
|
|
|
|
if (instructionLength > 5)
|
|
Nop(address + 5, instructionLength - 5);
|
|
}
|
|
|
|
template <typename Func>
|
|
Func Trampoline(DWORD address, Func hook, UINT instructionLength)
|
|
{
|
|
BYTE* gateway = static_cast<BYTE*>(
|
|
VirtualAlloc(nullptr, instructionLength + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));
|
|
|
|
ReadWriteProtect(address, instructionLength);
|
|
memcpy(gateway, reinterpret_cast<void*>(address), instructionLength);
|
|
|
|
Hook(address, hook, instructionLength, true);
|
|
Hook(reinterpret_cast<DWORD>(gateway + instructionLength), FunctionAt<Func>(address + instructionLength), 5, true);
|
|
|
|
return FunctionAt<Func>(reinterpret_cast<DWORD>(gateway));
|
|
}
|
|
|
|
template <typename Func>
|
|
void CleanupTrampoline(Func trampoline)
|
|
{
|
|
VirtualFree(reinterpret_cast<void*>(*reinterpret_cast<DWORD*>(&trampoline)), 0, MEM_RELEASE);
|
|
}
|
|
}
|