From 8bc0b41ed96db4c39e8da4e9f0b48a5d4aff6025 Mon Sep 17 00:00:00 2001 From: Dedmen Miller Date: Sat, 22 Feb 2020 20:05:48 +0100 Subject: [PATCH] Fix ScriptVM recording --- BIDebugEngine/BIDebugEngine/Debugger.cpp | 10 +- BIDebugEngine/BIDebugEngine/Debugger.h | 2 +- BIDebugEngine/BIDebugEngine/EngineHook.cpp | 57 ++++++-- BIDebugEngine/BIDebugEngine/EngineHook.h | 2 + .../BIDebugEngine/EngineHookfncx64.asm | 123 ++++++++++++++++-- .../BIDebugEngine/NetworkController.cpp | 8 +- BIDebugEngine/BIDebugEngine/dllmain.cpp | 33 ++++- 7 files changed, 195 insertions(+), 40 deletions(-) diff --git a/BIDebugEngine/BIDebugEngine/Debugger.cpp b/BIDebugEngine/BIDebugEngine/Debugger.cpp index 50ebd40..10ad5e3 100644 --- a/BIDebugEngine/BIDebugEngine/Debugger.cpp +++ b/BIDebugEngine/BIDebugEngine/Debugger.cpp @@ -164,7 +164,7 @@ Debugger::~Debugger() {} void Debugger::clear() { if (VMPtrToScript.empty()) return; - std::vector to_delete; + std::vector to_delete; to_delete.reserve(VMPtrToScript.size()); for (auto&it : VMPtrToScript) { if (it.second->canBeDeleted) @@ -181,12 +181,12 @@ void Debugger::clear() { } std::shared_ptr Debugger::getVMContext(RV_VMContext* vm) { - uintptr_t contentPtr = reinterpret_cast(vm); - auto iter(VMPtrToScript.lower_bound(contentPtr)); + //uintptr_t contentPtr = reinterpret_cast(vm); + auto iter(VMPtrToScript.lower_bound(vm)); //Thank you SO! - if (iter == VMPtrToScript.end() || contentPtr < iter->first) { // not found + if (iter == VMPtrToScript.end() || vm < iter->first) { // not found auto newEntry = std::make_shared(); - VMPtrToScript.insert(iter, { contentPtr, newEntry });// hinted insertion + VMPtrToScript.insert(iter, { vm, newEntry });// hinted insertion return newEntry; } return iter->second; diff --git a/BIDebugEngine/BIDebugEngine/Debugger.h b/BIDebugEngine/BIDebugEngine/Debugger.h index eeec5d7..827fc10 100644 --- a/BIDebugEngine/BIDebugEngine/Debugger.h +++ b/BIDebugEngine/BIDebugEngine/Debugger.h @@ -121,7 +121,7 @@ class Debugger { }; std::vector getVariables(VariableScope, std::vector& varName) const; void grabCurrentCode(JsonArchive& answer,const std::string& file) const; - std::map> VMPtrToScript; + std::map> VMPtrToScript; //std::map> breakPoints; class breakPointList : public std::vector { public: diff --git a/BIDebugEngine/BIDebugEngine/EngineHook.cpp b/BIDebugEngine/BIDebugEngine/EngineHook.cpp index d7296f4..f615f9d 100644 --- a/BIDebugEngine/BIDebugEngine/EngineHook.cpp +++ b/BIDebugEngine/BIDebugEngine/EngineHook.cpp @@ -63,6 +63,8 @@ extern "C" { uintptr_t hookEnabled_Simulate{ 1 }; uintptr_t scriptVM; uintptr_t currentScriptVM; + + uintptr_t scriptVMSimulateActual; } @@ -79,6 +81,7 @@ EngineEnableMouse* EngineEnableMouseFnc; extern "C" void scriptVMConstructor(); extern "C" void scriptVMSimulateStart(); +extern "C" void scriptVMSimulate(); extern "C" void scriptVMSimulateEnd(); extern "C" void instructionBreakpoint(); extern "C" void worldSimulate(); @@ -139,10 +142,24 @@ HookManager::Pattern pat_EngineEnableMouseFnc{//PROF only!!! "\x40\x57\x48\x83\xEC\x50\x38\x0D\x00\x00\x00\x00\x0F\xB6\xF9\x0F\x84\x00\x00\x00\x00\x8B\x05\x00\x00\x00\x00\x48\x89\x5C\x24\x00\x83\xCB\xFF\x48\x89\x74\x24\x00\x4C\x89\x74\x24\x00\xA8\x01\x75\x1A\x83\xC8\x01\x48\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00\x89\x1D\x00\x00\x00\x00\x89\x05\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x4C\x8D\x35\x00\x00\x00\x00\x75\x46\xE8\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x4C\x8D\x05\x00\x00\x00\x00" }; + +//146114 0000000000DE05C0 Not constructor! This adds to world vm list HookManager::Pattern pat_scriptVMConstructor{ - "xxxxxxxx????xxx????xxxxx????xxx????xxx????xxxxxxxx????xxxxxxxxxxxxxxxxxx", - "\x48\x8D\x4F\x20\x48\x8B\xD6\xE8\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8D\x4E\x20\xE8\x00\x00\x00\x00\x4C\x8D\x87\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8D\x4E\x20\x41\xB1\x01\xE8\x00\x00\x00\x00\x48\x8B\xC7\x48\x83\xC4\x60\x41\x5F\x41\x5E\x41\x5D\x5F\x5E\x5D\x5B\xC3", - 0x00000000013AD34E - 0x00000000013AD318 + "xxxx?xxxx?xxxx?xxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxx?????xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxx????xxxx????xxxxxx????xxxxxx????xxxx?xxxx?xxxx?xxxxxx", + "\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\x41\x0F\xB6\xE8\x48\x8B\xDA\x48\x85\xD2\x74\x04\xF0\xFF\x42\x08\x48\x8D\xB9\x00\x00\x00\x00\x44\x8B\x4F\x08\x8B\x4F\x10\x44\x3B\xC9\x7C\x26\xBA\x00\x00\x00\x00\x8B\xC1\xD1\xF8\x3B\xC2\x0F\x4C\xC2\x41\x8D\x14\x01\x41\x8D\x41\x01\x3B\xC8\x7C\x04\x3B\xCA\x7E\x08\x48\x8B\xCF\xE8\x00\x00\x00\x00\x48\x63\x47\x08\x48\xC1\xE0\x04\x48\x03\x07\x74\x13\x48\x85\xDB\x74\x04\xF0\xFF\x43\x08\x48\x89\x18\xC7\x40\x00\x00\x00\x00\x00\x8B\x77\x08\x8D\x46\x01\x89\x47\x08\x48\x85\xDB\x74\x0F\xF0\xFF\x4B\x08\x75\x09\x48\x8B\x03\x48\x8B\xCB\xFF\x50\x08\x40\x84\xED\x74\x2F\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8B\xCB\xF3\x0F\x10\x15\x00\x00\x00\x00\x0F\x57\xC9\xE8\x00\x00\x00\x00\x84\xC0\x74\x10\x41\xB8\x00\x00\x00\x00\x8B\xD6\x48\x8B\xCF\xE8\x00\x00\x00\x00\x48\x8B\x5C\x24\x00\x48\x8B\x6C\x24\x00\x48\x8B\x74\x24\x00\x48\x83\xC4\x20\x5F\xC3" +}; + +//146114 13504D0 +HookManager::Pattern pat_scriptVMSimulate{ + "xxxxxxxx?????xxxx?xxxxxxxxxxxxxx?xxxxxxxxxx?xxxx????xxxx????xxx????xxxxxxxx????xxxxx????xx", + "\x40\x56\x48\x83\xEC\x60\x80\xB9\x00\x00\x00\x00\x00\x0F\x29\x74\x24\x00\x48\x8B\xF1\x0F\x28\xF2\x75\x0D\x32\xC0\x0F\x28\x74\x24\x00\x48\x83\xC4\x60\x5E\xC3\x48\x89\x5C\x24\x00\x48\x89\xAC\x24\x00\x00\x00\x00\x48\x89\xBC\x24\x00\x00\x00\x00\x48\x8B\xB9\x00\x00\x00\x00\x48\x85\xFF\x75\x35\x40\x38\x3D\x00\x00\x00\x00\x74\x09\x48\x8D\x3D\x00\x00\x00\x00\xEB\x23" +}; + + +//146113 140FC90 +HookManager::Pattern pat_scriptVMSimulate_prof{ + "xxxxxxxx?xxx????xx?????xxxx?xxxxxxxxxxxxxx?xxx????xxxxxx????xxxx????xxxx????xxxxxxxxx????xxxx????xxxxxxxxxx????xx????xx????xxx????xxx????xxx????xxx????xxx????xxxxxxxxx????xxx????xxx????xx????x????xx?????xx????xxx????xxxx????xx?????xxxxxxxxxxxxxxxx????xxxxxxxx????xx????xxxxx????xxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxx????xxx????xx????xxxxxxxx????xxxxxxxxxxxxxxxxxx????xxx????xxxxx????xxxxxxxxxxxxxxx", + "\x40\x55\x41\x56\x48\x8D\x6C\x24\x00\x48\x81\xEC\x00\x00\x00\x00\x80\xB9\x00\x00\x00\x00\x00\x0F\x29\x74\x24\x00\x4C\x8B\xF1\x0F\x28\xF2\x75\x12\x32\xC0\x0F\x28\x74\x24\x00\x48\x81\xC4\x00\x00\x00\x00\x41\x5E\x5D\xC3\x8B\x05\x00\x00\x00\x00\x48\x89\x9C\x24\x00\x00\x00\x00\x48\x89\xB4\x24\x00\x00\x00\x00\x33\xF6\x83\xCB\xFF\x48\x89\xBC\x24\x00\x00\x00\x00\x4C\x89\xBC\x24\x00\x00\x00\x00\xA8\x01\x75\x16\x83\xC8\x01\x48\x89\x35\x00\x00\x00\x00\x89\x1D\x00\x00\x00\x00\x89\x05\x00\x00\x00\x00\x40\x38\x35\x00\x00\x00\x00\x4C\x8D\x3D\x00\x00\x00\x00\x75\x46\xE8\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x4C\x8D\x05\x00\x00\x00\x00\x49\x8B\xCF\x44\x8B\xC8\x4C\x89\x3D\x00\x00\x00\x00\x48\x89\x15\x00\x00\x00\x00\x4C\x89\x05\x00\x00\x00\x00\x89\x05\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xC6\x05\x00\x00\x00\x00\x00\x89\x05\x00\x00\x00\x00\x48\x8D\x3D\x00\x00\x00\x00\x48\x8B\xCF\xE8\x00\x00\x00\x00\x83\x3D\x00\x00\x00\x00\x00\x48\x89\x7D\x0F\x88\x45\x17\x48\x89\x75\x1F\x74\x42\x40\x38\x35\x00\x00\x00\x00\x75\x12\x84\xC0\x74\x35\xFF\x15\x00\x00\x00\x00\x39\x05\x00\x00\x00\x00\x75\x27\x40\x38\x35\x00\x00\x00\x00\xC6\x45\x18\x01\x74\x0F\x0F\x31\x48\xC1\xE2\x20\x48\x0B\xC2\x48\x89\x45\x07\xEB\x13\xE8\x00\x00\x00\x00\x48\x89\x45\x07\xEB\x08\x40\x88\x75\x18\x48\x89\x75\x07\x40\x38\x35\x00\x00\x00\x00\x48\x8D\x3D\x00\x00\x00\x00\x0F\x84\x00\x00\x00\x00\x48\x8D\x55\xE7\x49\x8B\xCE\xE8\x00\x00\x00\x00\x48\x8B\x08\x4C\x8D\x41\x10\x48\x85\xC9\x75\x03\x4C\x8B\xC7\x45\x8B\x8E\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8D\x4D\x7F\xE8\x00\x00\x00\x00\x48\x8B\x55\x1F\x48\x8B\x08\x48\x85\xC9\x74\x03\xF0\xFF\x01" }; HookManager::Pattern pat_scriptVMSimulateStart{//PROF ONLY @@ -152,9 +169,9 @@ HookManager::Pattern pat_scriptVMSimulateStart{//PROF ONLY HookManager::Pattern pat_scriptVMSimulateEnd{ - "xxxxxxxx????xxxxxxxxxxxxx????xxxxxxxxxx????xxxx?xxxxxxx????xxxx", - "\x48\x8B\x55\x1F\x4C\x8B\xA4\x24\x00\x00\x00\x00\x48\x85\xD2\x74\x12\xF0\xFF\x0A\x75\x0D\x48\x8B\x0D\x00\x00\x00\x00\x48\x8B\x01\xFF\x50\x18\x48\x8B\xBC\x24\x00\x00\x00\x00\x0F\x28\x74\x24\x00\x41\x0F\xB6\xC6\x48\x81\xC4\x00\x00\x00\x00\x41\x5E\x5D\xC3", - 0x00000000013ADF49 - 0x00000000013ADF1E + "xxxxxxx????xxxxxxx?x????xxx????xxxx????xxx????xxx????xxxx????xxxxxxxxxxxx????xxxx?xxxxxxxxxxxxxxxxxxxxx????xxxx?xxxxxxxxxx", + "\x4C\x8D\x4E\x18\x48\x8D\x15\x00\x00\x00\x00\x44\x8B\xC7\x48\x89\x44\x24\x00\xE8\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\x0F\xB6\xF0\xE8\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x89\x2D\x00\x00\x00\x00\x48\x8B\xAC\x24\x00\x00\x00\x00\x48\x85\xDB\x74\x04\xF0\xFF\x43\x08\x48\x89\x1D\x00\x00\x00\x00\x48\x8B\x5C\x24\x00\x48\x85\xC9\x74\x0C\xF0\xFF\x49\x08\x75\x06\x48\x8B\x01\xFF\x50\x08\x48\x8B\xBC\x24\x00\x00\x00\x00\x0F\x28\x74\x24\x00\x40\x0F\xB6\xC6\x48\x83\xC4\x60\x5E\xC3", + 0x1350623 - 0x13505C0 }; //HookManager::Pattern pat_instructionBreakpoint{ @@ -354,6 +371,8 @@ void EngineHook::placeHooks() { //char* productType = reinterpret_cast(GlobalHookManager.findPattern(pat_productType)); //char* productVersion = reinterpret_cast(GlobalHookManager.findPattern(pat_productVersion)); + auto vers = intercept::sqf::product_version(); + bool IsProfiling = vers.branch == "Profile"; //OutputDebugStringA("Product Type: "); //OutputDebugStringA(productType ? productType : ""); //OutputDebugStringA("\t\tVersion: "); @@ -473,10 +492,20 @@ void EngineHook::placeHooks() { #ifndef ScriptProfiling - HI.__scriptVMConstructor = true; + + HI.__scriptVMConstructor = GlobalHookManager.placeHook(hookTypes::scriptVMConstructor, pat_scriptVMConstructor, reinterpret_cast(scriptVMConstructor), scriptVMConstructorJmpBack, 6); + //HI.__scriptVMSimulateEnd = GlobalHookManager.placeHook(hookTypes::scriptVMSimulateEnd, pat_scriptVMSimulateEnd, reinterpret_cast(scriptVMSimulateEnd)); + + HI.__scriptVMSimulateEnd = HI.__scriptVMSimulateStart = GlobalHookManager.placeHookTrampoline(hookTypes::scriptVMSimulateStart, IsProfiling ? pat_scriptVMSimulate_prof : pat_scriptVMSimulate, reinterpret_cast(scriptVMSimulate), scriptVMSimulateActual, IsProfiling ? 0x22 : 0x18); + + //HI.__worldSimulate = GlobalHookManager.placeHook(hookTypes::worldSimulate, pat_worldSimulate, reinterpret_cast(worldSimulate), worldSimulateJmpBack, 0); + + + + //HI.__scriptVMConstructor = true; HI.__scriptVMSimulateStart = true; - HI.__scriptVMSimulateEnd = true; - HI.__worldSimulate = true; + //HI.__scriptVMSimulateEnd = true; + //HI.__worldSimulate = true; HI.__worldMissionEventStart = true; HI.__worldMissionEventEnd = true; #endif @@ -484,12 +513,12 @@ void EngineHook::placeHooks() { GlobalDebugger.setHookIntegrity(HI); if (! - ( //HI.__scriptVMConstructor + ( HI.__scriptVMConstructor //&& HI.__scriptVMSimulateStart - //&& HI.__scriptVMSimulateEnd - //&& + && HI.__scriptVMSimulateEnd + && HI.__instructionBreakpoint - //&& HI.__worldSimulate + && HI.__worldSimulate //&& HI.__worldMissionEventStart //&& HI.__worldMissionEventEnd && HI.__onScriptError @@ -606,7 +635,7 @@ void EngineHook::_scriptTerminated(uintptr_t scrVMPtr) { GlobalDebugger.getVMContext(&scVM->_context)->dbg_LeaveContext(); auto myCtx = GlobalDebugger.getVMContext(&scVM->_context); //scVM->debugPrint("Term " + std::to_string(myCtx->totalRuntime.count())); - if (scVM->_context.callstack.count() - 1 > 0) { + if (scVM->_context.callstack.count() > 1) { auto scope = scVM->_context.callstack.back(); printAllVariables(*scope); } diff --git a/BIDebugEngine/BIDebugEngine/EngineHook.h b/BIDebugEngine/BIDebugEngine/EngineHook.h index 45b4f4c..92bd49e 100644 --- a/BIDebugEngine/BIDebugEngine/EngineHook.h +++ b/BIDebugEngine/BIDebugEngine/EngineHook.h @@ -40,9 +40,11 @@ class HookManager {//Implementation in dllmain HookManager(); bool placeHook(hookTypes, const Pattern& pat, uintptr_t jmpTo, uintptr_t& jmpBackRef, uint8_t jmpBackOffset = 0); + bool placeHookTrampoline(hookTypes hook_types_, const Pattern& pattern_, uintptr_t jmpTo, uintptr_t& origFunctionRef, uint32_t trampolineSize); bool placeHook(hookTypes, const Pattern& pat, uintptr_t jmpTo); uintptr_t placeHook(uintptr_t offset, uintptr_t jmpTo, uint8_t jmpBackOffset = 0); uintptr_t placeHookTotalOffs(uintptr_t offset, uintptr_t jmpTo); + void placeHookTrampolineTotalOffs(uintptr_t found_, uintptr_t jmp_to_, uintptr_t& orig_function_ref_, uint32_t trampoline_size_); bool MatchPattern(uintptr_t addr, const char* pattern, const char* mask); uintptr_t findPattern(const char* pattern, const char* mask, uintptr_t offset = 0); uintptr_t findPattern(const Pattern& pat, uintptr_t offset = 0); diff --git a/BIDebugEngine/BIDebugEngine/EngineHookfncx64.asm b/BIDebugEngine/BIDebugEngine/EngineHookfncx64.asm index 463466d..c76cd2c 100644 --- a/BIDebugEngine/BIDebugEngine/EngineHookfncx64.asm +++ b/BIDebugEngine/BIDebugEngine/EngineHookfncx64.asm @@ -25,6 +25,9 @@ _TEXT SEGMENT EXTERN instructionBreakpointJmpBack: qword EXTERN scriptVMSimulateStartJmpBack: qword + + EXTERN scriptVMSimulateActual: qword + EXTERN worldSimulateJmpBack: qword EXTERN worldMissionEventStartJmpBack: qword EXTERN worldMissionEventEndJmpBack: qword @@ -89,24 +92,43 @@ _TEXT SEGMENT PUBLIC scriptVMConstructor scriptVMConstructor PROC + push rax; + push rcx; + push rdx; + push r8; + push r9; + push r10; + push r11; + push rcx; push rdx; - mov rdx, rdi; scriptVM Pointer + ; rdx scriptVM Pointer mov rcx, offset GlobalEngineHook; call ?_scriptLoaded@EngineHook@@QEAAX_K@Z; EngineHook::_scriptLoaded; ;_return: - pop rdx; - pop rcx; - mov rax, rdi; Fixup - add rsp, 60h - pop r15 - pop r14 - pop r13 - pop rdi - pop rsi - pop rbp - pop rbx + pop rdx; + pop rcx; + + pop r11; + pop r10; + pop r9; + pop r8; + pop rdx; + pop rcx; + pop rax; + + + + + mov [rsp+8], rbx ; fixup + mov [rsp+10h], rbp + mov [rsp+20h], rsi + push rdi + sub rsp, 20h + ;movzx ebp, r8b + ;mov rbx, rdx + ;test rdx, rdx jmp scriptVMConstructorJmpBack; scriptVMConstructor ENDP @@ -188,6 +210,83 @@ _TEXT SEGMENT pop rbp ret scriptVMSimulateEnd ENDP + + + PUBLIC scriptVMSimulate + scriptVMSimulate PROC + + push rcx; + push rdx; + push r8; + push r9; + push r10; + push r11; + + + push rcx; scriptVM is at [rsp+10h] + + mov rcx, hookEnabled_Simulate; Skip if hook is disabled + test rcx, rcx; + jz _return; + + pop rcx; + push rcx; + + push rcx; + push rdx; + + mov rdx, rcx; _scriptEntered arg + mov rcx, offset GlobalEngineHook; + call ?_scriptEntered@EngineHook@@QEAAX_K@Z; EngineHook::_scriptEntered; + + + pop rdx; + pop rcx; + + + + call scriptVMSimulateActual; + + pop rcx; + push rdx; + + mov rdx, rcx; scriptVM + mov rcx, offset GlobalEngineHook; + + test eax, eax; rdi == done + jz _notDone; script is not Done + call ?_scriptTerminated@EngineHook@@QEAAX_K@Z; EngineHook::_scriptTerminated; script is Done + mov rax, 1 + jmp _returnPostCall; + _notDone: + call ?_scriptLeft@EngineHook@@QEAAX_K@Z; EngineHook::_scriptLeft; + + + _returnPostCall: + + pop rdx; + + pop r11; + pop r10; + pop r9; + pop r8; + pop rdx; + pop rcx; + ret + + + _return: + pop rcx; + pop r11; + pop r10; + pop r9; + pop r8; + pop rdx; + pop rcx; + call scriptVMSimulateActual; + ret + + scriptVMSimulate ENDP ;########## PUBLIC worldSimulate diff --git a/BIDebugEngine/BIDebugEngine/NetworkController.cpp b/BIDebugEngine/BIDebugEngine/NetworkController.cpp index 4940909..64d6071 100644 --- a/BIDebugEngine/BIDebugEngine/NetworkController.cpp +++ b/BIDebugEngine/BIDebugEngine/NetworkController.cpp @@ -218,14 +218,12 @@ void NetworkController::incomingMessage(const std::string& message) { case NC_CommandType::LoadFile: { if (GlobalDebugger.state != DebuggerState::breakState) { - answer.Serialize("exception", "getCurrentCode: Not in breakState!"); + JsonArchive answer; + answer.Serialize("handle", packet.value("handle", {})); + answer.Serialize("exception", "LoadFile: Not in breakState!"); return; } - - intercept::client::invoker_lock lock(true); - if (GlobalDebugger.state != DebuggerState::breakState) lock.lock(); - JsonArchive ar(packet["data"]); r_string path; diff --git a/BIDebugEngine/BIDebugEngine/dllmain.cpp b/BIDebugEngine/BIDebugEngine/dllmain.cpp index d54ecd7..e6487a0 100644 --- a/BIDebugEngine/BIDebugEngine/dllmain.cpp +++ b/BIDebugEngine/BIDebugEngine/dllmain.cpp @@ -205,12 +205,21 @@ bool HookManager::placeHook(hookTypes type, const Pattern& pat, uintptr_t jmpTo, return true; } +bool HookManager::placeHookTrampoline(hookTypes, const Pattern& pat, uintptr_t jmpTo, uintptr_t& origFunctionRef, uint32_t trampolineSize) { + auto found = findPattern(pat); + if (found == 0) { + return false; + } + placeHookTrampolineTotalOffs(found, jmpTo, origFunctionRef, trampolineSize); + return true; +} + bool HookManager::placeHook(hookTypes, const Pattern & pat, uintptr_t jmpTo) { auto found = findPattern(pat); if (found == 0) { -#ifdef _DEBUG - __debugbreak(); //#TODO report somehow -#endif +//#ifdef _DEBUG +// __debugbreak(); //#TODO report somehow +//#endif return false; } placeHookTotalOffs(found, jmpTo); @@ -260,6 +269,24 @@ uintptr_t HookManager::placeHookTotalOffs(uintptr_t totalOffset, uintptr_t jmpTo } +void HookManager::placeHookTrampolineTotalOffs(uintptr_t totalOffset, uintptr_t jmpTo, uintptr_t& orig_function_ref_, uint32_t trampolineSize) { + auto trampoline = (uintptr_t)malloc(trampolineSize + 50); + + memcpy((void*)trampoline, (void*)totalOffset, trampolineSize); + + //After trampoline, jump back to original function + placeHookTotalOffs(trampoline + trampolineSize, totalOffset + trampolineSize); + + DWORD dwVirtualProtectBackup; + //Make trampoline executable + VirtualProtect(reinterpret_cast(trampoline), trampolineSize + 14u, 0x40u, &dwVirtualProtectBackup); + + orig_function_ref_ = trampoline; + + placeHookTotalOffs(totalOffset, jmpTo); //Jmp to our target +} + + bool HookManager::MatchPattern(uintptr_t addr, const char* pattern, const char* mask) { size_t size = strlen(mask); if (IsBadReadPtr((void*) addr, size))