iw4x-client/src/Utils/Hooking.hpp

180 lines
5.0 KiB
C++
Raw Normal View History

2015-12-23 08:45:53 -05:00
#pragma once
#define HOOK_JUMP true
#define HOOK_CALL false
namespace Utils
{
class Hook
{
public:
2016-06-14 13:49:27 -04:00
class Signature
{
public:
struct Container
{
const char* Signature;
const char* Mask;
std::function<void(char*)> Callback;
};
Signature(void* start, size_t length) : Start(start), Length(length) {}
Signature(DWORD start, size_t length) : Signature(reinterpret_cast<void*>(start), length) {}
Signature() : Signature(0x400000, 0x800000) {}
void Process();
void Add(Container& container);
private:
void* Start;
size_t Length;
std::vector<Container> Signatures;
};
2016-04-08 10:15:01 -04:00
class Interceptor
{
public:
static void Install(void* place, void(*stub)());
static void Install(void** place, void(*stub)());
private:
static std::map<void*, void*> IReturn;
static std::map<void*, void(*)()> ICallbacks;
static void InterceptionStub();
static void RunCallback(void* place);
static void* PopReturn(void* place);
};
2016-01-24 15:08:14 -05:00
Hook() : Place(nullptr), Stub(nullptr), Initialized(false), Installed(false), Original(0), UseJump(false), Protection(0) { ZeroMemory(Hook::Buffer, sizeof(Hook::Buffer)); }
2016-03-01 07:37:51 -05:00
2015-12-23 08:45:53 -05:00
Hook(void* place, void* stub, bool useJump = true) : Hook() { Hook::Initialize(place, stub, useJump); }
2016-03-01 07:37:51 -05:00
Hook(void* place, void(*stub)(), bool useJump = true) : Hook(place, reinterpret_cast<void*>(stub), useJump) {}
Hook(DWORD place, void* stub, bool useJump = true) : Hook(reinterpret_cast<void*>(place), stub, useJump) {}
Hook(DWORD place, DWORD stub, bool useJump = true) : Hook(reinterpret_cast<void*>(place), reinterpret_cast<void*>(stub), useJump) {}
Hook(DWORD place, void(*stub)(), bool useJump = true) : Hook(reinterpret_cast<void*>(place), reinterpret_cast<void*>(stub), useJump) {}
2015-12-23 08:45:53 -05:00
~Hook();
Hook* Initialize(void* place, void* stub, bool useJump = true);
Hook* Initialize(DWORD place, void* stub, bool useJump = true);
2015-12-28 08:08:46 -05:00
Hook* Initialize(DWORD place, void(*stub)(), bool useJump = true); // For lambdas
2016-03-14 16:29:21 -04:00
Hook* Install(bool unprotect = true, bool keepUnportected = false);
Hook* Uninstall(bool unprotect = true);
2015-12-23 08:45:53 -05:00
void* GetAddress();
void Quick();
2016-01-01 20:47:15 -05:00
template <typename T> static std::function<T> Call(DWORD function)
2015-12-26 21:56:00 -05:00
{
return std::function<T>(reinterpret_cast<T*>(function));
2015-12-26 21:56:00 -05:00
}
2016-01-07 10:55:10 -05:00
template <typename T> static std::function<T> Call(FARPROC function)
{
return Call<T>(reinterpret_cast<DWORD>(function));
2016-01-07 10:55:10 -05:00
}
2015-12-30 16:22:24 -05:00
static void SetString(void* place, const char* string, size_t length);
static void SetString(DWORD place, const char* string, size_t length);
static void SetString(void* place, const char* string);
static void SetString(DWORD place, const char* string);
2015-12-23 08:45:53 -05:00
static void Nop(void* place, size_t length);
static void Nop(DWORD place, size_t length);
2016-02-11 18:36:52 -05:00
static void RedirectJump(void* place, void* stub);
static void RedirectJump(DWORD place, void* stub);
2015-12-23 08:45:53 -05:00
template <typename T> static void Set(void* place, T value)
{
2016-02-29 09:49:27 -05:00
DWORD oldProtect;
VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect);
*static_cast<T*>(place) = value;
2016-02-29 09:49:27 -05:00
VirtualProtect(place, sizeof(T), oldProtect, &oldProtect);
2015-12-23 08:45:53 -05:00
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
}
template <typename T> static void Set(DWORD place, T value)
{
return Set<T>(reinterpret_cast<void*>(place), value);
2015-12-23 08:45:53 -05:00
}
2015-12-23 09:00:01 -05:00
template <typename T> static void Xor(void* place, T value)
{
2016-02-29 09:49:27 -05:00
DWORD oldProtect;
VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect);
*static_cast<T*>(place) ^= value;
2016-02-29 09:49:27 -05:00
VirtualProtect(place, sizeof(T), oldProtect, &oldProtect);
2015-12-23 09:00:01 -05:00
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
}
template <typename T> static void Xor(DWORD place, T value)
{
return Xor<T>(reinterpret_cast<void*>(place), value);
2015-12-23 09:00:01 -05:00
}
template <typename T> static void Or(void* place, T value)
{
2016-02-29 09:49:27 -05:00
DWORD oldProtect;
VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect);
*static_cast<T*>(place) |= value;
2016-02-29 09:49:27 -05:00
VirtualProtect(place, sizeof(T), oldProtect, &oldProtect);
2015-12-23 09:00:01 -05:00
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
}
template <typename T> static void Or(DWORD place, T value)
{
return Or<T>(reinterpret_cast<void*>(place), value);
2015-12-23 09:00:01 -05:00
}
template <typename T> static void And(void* place, T value)
{
2016-02-29 09:49:27 -05:00
DWORD oldProtect;
VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect);
*static_cast<T*>(place) &= value;
2016-02-29 09:49:27 -05:00
VirtualProtect(place, sizeof(T), oldProtect, &oldProtect);
2015-12-23 09:00:01 -05:00
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
}
template <typename T> static void And(DWORD place, T value)
{
return And<T>(reinterpret_cast<void*>(place), value);
2015-12-23 09:00:01 -05:00
}
2015-12-23 08:45:53 -05:00
template <typename T> static T Get(void* place)
{
return *static_cast<T*>(place);
2015-12-23 08:45:53 -05:00
}
template <typename T> static T Get(DWORD place)
{
return Get<T>(reinterpret_cast<void*>(place));
2015-12-23 08:45:53 -05:00
}
private:
bool Initialized;
bool Installed;
void* Place;
void* Stub;
2015-12-23 11:12:15 -05:00
void* Original;
2015-12-23 08:45:53 -05:00
char Buffer[5];
bool UseJump;
2015-12-30 16:22:24 -05:00
DWORD Protection;
2015-12-23 08:45:53 -05:00
std::mutex StateMutex;
};
}