Add a stack-frame hooking class
This commit is contained in:
parent
b912eb618b
commit
19b6a12c92
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 452e2b2c5c607ab5d63cd813793f1aa960f19d1c
|
Subproject commit 667f4a6282f9d7e7edb0acc8758e384b17a0359d
|
@ -2,6 +2,67 @@
|
|||||||
|
|
||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
|
std::map<void*, void*> Hook::Interceptor::IReturn;
|
||||||
|
std::map<void*, void(*)()> Hook::Interceptor::ICallbacks;
|
||||||
|
|
||||||
|
void Hook::Interceptor::Install(void* place, void(*stub)())
|
||||||
|
{
|
||||||
|
return Hook::Interceptor::Install(reinterpret_cast<void**>(place), stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hook::Interceptor::Install(void** place, void(*stub)())
|
||||||
|
{
|
||||||
|
Hook::Interceptor::IReturn[place] = *place;
|
||||||
|
Hook::Interceptor::ICallbacks[place] = stub;
|
||||||
|
*place = Hook::Interceptor::InterceptionStub;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __declspec(naked) Hook::Interceptor::InterceptionStub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
sub esp, 4h // Reserve space on the stack for the return address
|
||||||
|
pushad // Store registers
|
||||||
|
|
||||||
|
lea eax, [esp + 20h] // Load initial stack pointer
|
||||||
|
push eax // Push it onto the stack
|
||||||
|
|
||||||
|
call RunCallback // Run the callback based on the given stack pointer
|
||||||
|
call PopReturn // Get the initial return address according to the stack pointer
|
||||||
|
|
||||||
|
add esp, 4h // Clear the stack
|
||||||
|
|
||||||
|
mov [esp + 20h], eax // Store the return address at the reserves space
|
||||||
|
popad // Restore the registers
|
||||||
|
|
||||||
|
retn // Return (jump to our return address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hook::Interceptor::RunCallback(void* place)
|
||||||
|
{
|
||||||
|
auto iCallback = Hook::Interceptor::ICallbacks.find(place);
|
||||||
|
if (iCallback != Hook::Interceptor::ICallbacks.end())
|
||||||
|
{
|
||||||
|
iCallback->second();
|
||||||
|
Hook::Interceptor::ICallbacks.erase(iCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Hook::Interceptor::PopReturn(void* place)
|
||||||
|
{
|
||||||
|
void* retVal = nullptr;
|
||||||
|
|
||||||
|
auto iReturn = Hook::Interceptor::IReturn.find(place);
|
||||||
|
if (iReturn != Hook::Interceptor::IReturn.end())
|
||||||
|
{
|
||||||
|
retVal = iReturn->second;
|
||||||
|
Hook::Interceptor::IReturn.erase(iReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
Hook::~Hook()
|
Hook::~Hook()
|
||||||
{
|
{
|
||||||
if (Hook::Initialized)
|
if (Hook::Initialized)
|
||||||
|
@ -8,6 +8,21 @@ namespace Utils
|
|||||||
class Hook
|
class Hook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
Hook() : Place(nullptr), Stub(nullptr), Initialized(false), Installed(false), Original(0), UseJump(false), Protection(0) { ZeroMemory(Hook::Buffer, sizeof(Hook::Buffer)); }
|
Hook() : Place(nullptr), Stub(nullptr), Initialized(false), Installed(false), Original(0), UseJump(false), Protection(0) { ZeroMemory(Hook::Buffer, sizeof(Hook::Buffer)); }
|
||||||
|
|
||||||
Hook(void* place, void* stub, bool useJump = true) : Hook() { Hook::Initialize(place, stub, useJump); }
|
Hook(void* place, void* stub, bool useJump = true) : Hook() { Hook::Initialize(place, stub, useJump); }
|
||||||
|
Loading…
Reference in New Issue
Block a user