From 19b6a12c928a6c3cec5f92226edcb3d53a19e479 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 8 Apr 2016 16:15:01 +0200 Subject: [PATCH] Add a stack-frame hooking class --- deps/protobuf | 2 +- src/Utils/Hooking.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++ src/Utils/Hooking.hpp | 15 +++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/deps/protobuf b/deps/protobuf index 452e2b2c..667f4a62 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit 452e2b2c5c607ab5d63cd813793f1aa960f19d1c +Subproject commit 667f4a6282f9d7e7edb0acc8758e384b17a0359d diff --git a/src/Utils/Hooking.cpp b/src/Utils/Hooking.cpp index 6a59650c..4957384e 100644 --- a/src/Utils/Hooking.cpp +++ b/src/Utils/Hooking.cpp @@ -2,6 +2,67 @@ namespace Utils { + std::map Hook::Interceptor::IReturn; + std::map Hook::Interceptor::ICallbacks; + + void Hook::Interceptor::Install(void* place, void(*stub)()) + { + return Hook::Interceptor::Install(reinterpret_cast(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() { if (Hook::Initialized) diff --git a/src/Utils/Hooking.hpp b/src/Utils/Hooking.hpp index f3e44db1..84442603 100644 --- a/src/Utils/Hooking.hpp +++ b/src/Utils/Hooking.hpp @@ -8,6 +8,21 @@ namespace Utils class Hook { public: + class Interceptor + { + public: + static void Install(void* place, void(*stub)()); + static void Install(void** place, void(*stub)()); + + private: + static std::map IReturn; + static std::map 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(void* place, void* stub, bool useJump = true) : Hook() { Hook::Initialize(place, stub, useJump); }