diff --git a/include/safetyhook/context.hpp b/include/safetyhook/context.hpp index c763f08..049516b 100644 --- a/include/safetyhook/context.hpp +++ b/include/safetyhook/context.hpp @@ -19,18 +19,22 @@ union Xmm { /// @details This structure is used to pass the context of the hooked function to the destination allowing full access /// to the 64-bit registers at the moment the hook is called. /// @note rip will point to a trampoline containing the replaced instruction(s). +/// @note rsp is read-only. Modifying it will have no effect. Use trampoline_rsp to modify rsp if needed but make sure +/// the top of the stack is the rip you want to resume at. struct Context64 { Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15; - uintptr_t rflags, r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax, rbp, rsp, rip; + uintptr_t rflags, r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax, rbp, rsp, trampoline_rsp, rip; }; /// @brief Context structure for 32-bit MidHook. /// @details This structure is used to pass the context of the hooked function to the destination allowing full access /// to the 32-bit registers at the moment the hook is called. /// @note eip will point to a trampoline containing the replaced instruction(s). +/// @note esp is read-only. Modifying it will have no effect. Use trampoline_esp to modify esp if needed but make sure +/// the top of the stack is the eip you want to resume at. struct Context32 { Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; - uintptr_t eflags, edi, esi, edx, ecx, ebx, eax, ebp, esp, eip; + uintptr_t eflags, edi, esi, edx, ecx, ebx, eax, ebp, esp, trampoline_esp, eip; }; /// @brief Context structure for MidHook. diff --git a/src/mid_hook.cpp b/src/mid_hook.cpp index dd879c3..7b5ce73 100644 --- a/src/mid_hook.cpp +++ b/src/mid_hook.cpp @@ -10,36 +10,38 @@ namespace safetyhook { #ifdef _M_X64 -constexpr auto asm_data = std::to_array({0xff, 0x35, 0x5c, 0x01, 0x00, 0x00, 0x54, 0x55, 0x50, 0x53, 0x51, +constexpr std::array asm_data = {0xFF, 0x35, 0x76, 0x01, 0x00, 0x00, 0x54, 0x54, 0x55, 0x50, 0x53, 0x51, 0x52, 0x56, 0x57, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, - 0x9c, 0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x7f, 0xbc, 0x24, 0x10, 0xff, 0xff, 0xff, 0xf3, - 0x44, 0x0f, 0x7f, 0xb4, 0x24, 0x20, 0xff, 0xff, 0xff, 0xf3, 0x44, 0x0f, 0x7f, 0xac, 0x24, 0x30, 0xff, 0xff, 0xff, - 0xf3, 0x44, 0x0f, 0x7f, 0xa4, 0x24, 0x40, 0xff, 0xff, 0xff, 0xf3, 0x44, 0x0f, 0x7f, 0x9c, 0x24, 0x50, 0xff, 0xff, - 0xff, 0xf3, 0x44, 0x0f, 0x7f, 0x94, 0x24, 0x60, 0xff, 0xff, 0xff, 0xf3, 0x44, 0x0f, 0x7f, 0x8c, 0x24, 0x70, 0xff, - 0xff, 0xff, 0xf3, 0x44, 0x0f, 0x7f, 0x44, 0x24, 0x80, 0xf3, 0x0f, 0x7f, 0x7c, 0x24, 0x90, 0xf3, 0x0f, 0x7f, 0x74, - 0x24, 0xa0, 0xf3, 0x0f, 0x7f, 0x6c, 0x24, 0xb0, 0xf3, 0x0f, 0x7f, 0x64, 0x24, 0xc0, 0xf3, 0x0f, 0x7f, 0x5c, 0x24, - 0xd0, 0xf3, 0x0f, 0x7f, 0x54, 0x24, 0xe0, 0xf3, 0x0f, 0x7f, 0x4c, 0x24, 0xf0, 0xf3, 0x0f, 0x7f, 0x04, 0x24, 0x48, - 0x8d, 0x0c, 0x24, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x30, 0x48, 0x83, 0xe4, 0xf0, 0xff, 0x15, 0xa3, 0x00, 0x00, - 0x00, 0x48, 0x89, 0xdc, 0xf3, 0x0f, 0x6f, 0x04, 0x24, 0xf3, 0x0f, 0x6f, 0x4c, 0x24, 0x10, 0xf3, 0x0f, 0x6f, 0x54, - 0x24, 0x20, 0xf3, 0x0f, 0x6f, 0x5c, 0x24, 0x30, 0xf3, 0x0f, 0x6f, 0x64, 0x24, 0x40, 0xf3, 0x0f, 0x6f, 0x6c, 0x24, - 0x50, 0xf3, 0x0f, 0x6f, 0x74, 0x24, 0x60, 0xf3, 0x0f, 0x6f, 0x7c, 0x24, 0x70, 0xf3, 0x44, 0x0f, 0x6f, 0x84, 0x24, - 0x80, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x6f, 0x8c, 0x24, 0x90, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x6f, 0x94, - 0x24, 0xa0, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x6f, 0x9c, 0x24, 0xb0, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x6f, - 0xa4, 0x24, 0xc0, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x6f, 0xac, 0x24, 0xd0, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, - 0x6f, 0xb4, 0x24, 0xe0, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x0f, 0x6f, 0xbc, 0x24, 0xf0, 0x00, 0x00, 0x00, 0x48, 0x81, - 0xc4, 0x00, 0x01, 0x00, 0x00, 0x9d, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x41, 0x5b, 0x41, 0x5a, 0x41, - 0x59, 0x41, 0x58, 0x5f, 0x5e, 0x5a, 0x59, 0x5b, 0x58, 0x5d, 0x5c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + 0x9C, 0x48, 0x81, 0xEC, 0x00, 0x01, 0x00, 0x00, 0xF3, 0x44, 0x0F, 0x7F, 0xBC, 0x24, 0x10, 0xFF, 0xFF, 0xFF, 0xF3, + 0x44, 0x0F, 0x7F, 0xB4, 0x24, 0x20, 0xFF, 0xFF, 0xFF, 0xF3, 0x44, 0x0F, 0x7F, 0xAC, 0x24, 0x30, 0xFF, 0xFF, 0xFF, + 0xF3, 0x44, 0x0F, 0x7F, 0xA4, 0x24, 0x40, 0xFF, 0xFF, 0xFF, 0xF3, 0x44, 0x0F, 0x7F, 0x9C, 0x24, 0x50, 0xFF, 0xFF, + 0xFF, 0xF3, 0x44, 0x0F, 0x7F, 0x94, 0x24, 0x60, 0xFF, 0xFF, 0xFF, 0xF3, 0x44, 0x0F, 0x7F, 0x8C, 0x24, 0x70, 0xFF, + 0xFF, 0xFF, 0xF3, 0x44, 0x0F, 0x7F, 0x44, 0x24, 0x80, 0xF3, 0x0F, 0x7F, 0x7C, 0x24, 0x90, 0xF3, 0x0F, 0x7F, 0x74, + 0x24, 0xA0, 0xF3, 0x0F, 0x7F, 0x6C, 0x24, 0xB0, 0xF3, 0x0F, 0x7F, 0x64, 0x24, 0xC0, 0xF3, 0x0F, 0x7F, 0x5C, 0x24, + 0xD0, 0xF3, 0x0F, 0x7F, 0x54, 0x24, 0xE0, 0xF3, 0x0F, 0x7F, 0x4C, 0x24, 0xF0, 0xF3, 0x0F, 0x7F, 0x04, 0x24, 0x48, + 0x8B, 0x8C, 0x24, 0x80, 0x01, 0x00, 0x00, 0x48, 0x83, 0xC1, 0x10, 0x48, 0x89, 0x8C, 0x24, 0x80, 0x01, 0x00, 0x00, + 0x48, 0x8D, 0x0C, 0x24, 0x48, 0x89, 0xE3, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x83, 0xE4, 0xF0, 0xFF, 0x15, 0xA8, 0x00, + 0x00, 0x00, 0x48, 0x89, 0xDC, 0xF3, 0x0F, 0x6F, 0x04, 0x24, 0xF3, 0x0F, 0x6F, 0x4C, 0x24, 0x10, 0xF3, 0x0F, 0x6F, + 0x54, 0x24, 0x20, 0xF3, 0x0F, 0x6F, 0x5C, 0x24, 0x30, 0xF3, 0x0F, 0x6F, 0x64, 0x24, 0x40, 0xF3, 0x0F, 0x6F, 0x6C, + 0x24, 0x50, 0xF3, 0x0F, 0x6F, 0x74, 0x24, 0x60, 0xF3, 0x0F, 0x6F, 0x7C, 0x24, 0x70, 0xF3, 0x44, 0x0F, 0x6F, 0x84, + 0x24, 0x80, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x0F, 0x6F, 0x8C, 0x24, 0x90, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x0F, 0x6F, + 0x94, 0x24, 0xA0, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x0F, 0x6F, 0x9C, 0x24, 0xB0, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x0F, + 0x6F, 0xA4, 0x24, 0xC0, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x0F, 0x6F, 0xAC, 0x24, 0xD0, 0x00, 0x00, 0x00, 0xF3, 0x44, + 0x0F, 0x6F, 0xB4, 0x24, 0xE0, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x0F, 0x6F, 0xBC, 0x24, 0xF0, 0x00, 0x00, 0x00, 0x48, + 0x81, 0xC4, 0x00, 0x01, 0x00, 0x00, 0x9D, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x41, 0x5B, 0x41, 0x5A, + 0x41, 0x59, 0x41, 0x58, 0x5F, 0x5E, 0x5A, 0x59, 0x5B, 0x58, 0x5D, 0x48, 0x8D, 0x64, 0x24, 0x08, 0x5C, 0xC3, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #else -constexpr auto asm_data = std::to_array({0xff, 0x35, 0x91, 0x00, 0x00, 0x00, 0x54, 0x55, 0x50, 0x53, 0x51, - 0x52, 0x56, 0x57, 0x9c, 0x81, 0xec, 0x80, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x7f, 0x7c, 0x24, 0x90, 0xf3, 0x0f, 0x7f, - 0x74, 0x24, 0xa0, 0xf3, 0x0f, 0x7f, 0x6c, 0x24, 0xb0, 0xf3, 0x0f, 0x7f, 0x64, 0x24, 0xc0, 0xf3, 0x0f, 0x7f, 0x5c, - 0x24, 0xd0, 0xf3, 0x0f, 0x7f, 0x54, 0x24, 0xe0, 0xf3, 0x0f, 0x7f, 0x4c, 0x24, 0xf0, 0xf3, 0x0f, 0x7f, 0x04, 0x24, - 0x54, 0xff, 0x15, 0x8d, 0x00, 0x00, 0x00, 0x83, 0xc4, 0x04, 0xf3, 0x0f, 0x6f, 0x04, 0x24, 0xf3, 0x0f, 0x6f, 0x4c, - 0x24, 0x10, 0xf3, 0x0f, 0x6f, 0x54, 0x24, 0x20, 0xf3, 0x0f, 0x6f, 0x5c, 0x24, 0x30, 0xf3, 0x0f, 0x6f, 0x64, 0x24, - 0x40, 0xf3, 0x0f, 0x6f, 0x6c, 0x24, 0x50, 0xf3, 0x0f, 0x6f, 0x74, 0x24, 0x60, 0xf3, 0x0f, 0x6f, 0x7c, 0x24, 0x70, - 0x81, 0xc4, 0x80, 0x00, 0x00, 0x00, 0x9d, 0x5f, 0x5e, 0x5a, 0x59, 0x5b, 0x58, 0x5d, 0x5c, 0xc3, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}); +constexpr std::array asm_data = {0xFF, 0x35, 0xA7, 0x00, 0x00, 0x00, 0x54, 0x54, 0x55, 0x50, 0x53, 0x51, + 0x52, 0x56, 0x57, 0x9C, 0x81, 0xEC, 0x80, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x7F, 0x7C, 0x24, 0x90, 0xF3, 0x0F, 0x7F, + 0x74, 0x24, 0xA0, 0xF3, 0x0F, 0x7F, 0x6C, 0x24, 0xB0, 0xF3, 0x0F, 0x7F, 0x64, 0x24, 0xC0, 0xF3, 0x0F, 0x7F, 0x5C, + 0x24, 0xD0, 0xF3, 0x0F, 0x7F, 0x54, 0x24, 0xE0, 0xF3, 0x0F, 0x7F, 0x4C, 0x24, 0xF0, 0xF3, 0x0F, 0x7F, 0x04, 0x24, + 0x8B, 0x8C, 0x24, 0xC0, 0x00, 0x00, 0x00, 0x83, 0xC1, 0x08, 0x89, 0x8C, 0x24, 0xC0, 0x00, 0x00, 0x00, 0x54, 0xFF, + 0x15, 0xA3, 0x00, 0x00, 0x00, 0x83, 0xC4, 0x04, 0xF3, 0x0F, 0x6F, 0x04, 0x24, 0xF3, 0x0F, 0x6F, 0x4C, 0x24, 0x10, + 0xF3, 0x0F, 0x6F, 0x54, 0x24, 0x20, 0xF3, 0x0F, 0x6F, 0x5C, 0x24, 0x30, 0xF3, 0x0F, 0x6F, 0x64, 0x24, 0x40, 0xF3, + 0x0F, 0x6F, 0x6C, 0x24, 0x50, 0xF3, 0x0F, 0x6F, 0x74, 0x24, 0x60, 0xF3, 0x0F, 0x6F, 0x7C, 0x24, 0x70, 0x81, 0xC4, + 0x80, 0x00, 0x00, 0x00, 0x9D, 0x5F, 0x5E, 0x5A, 0x59, 0x5B, 0x58, 0x5D, 0x8D, 0x64, 0x24, 0x04, 0x5C, 0xC3, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif std::expected MidHook::create(void* target, MidHookFn destination) { @@ -102,7 +104,7 @@ std::expected MidHook::setup( // 32-bit has some relocations we need to fix up as well. store(m_stub.data() + 0x02, m_stub.data() + m_stub.size() - 4); - store(m_stub.data() + 0x47, m_stub.data() + m_stub.size() - 8); + store(m_stub.data() + 0x59, m_stub.data() + m_stub.size() - 8); #endif auto hook_result = InlineHook::create(allocator, m_target, m_stub.data()); diff --git a/src/mid_hook.x86.asm b/src/mid_hook.x86.asm index b648d2f..b6ef67c 100644 --- a/src/mid_hook.x86.asm +++ b/src/mid_hook.x86.asm @@ -2,7 +2,8 @@ bits 32 ; save context push dword [trampoline] -push esp +push esp ; push trampoline esp +push esp ; push original esp (this gets fixed later) push ebp push eax push ebx @@ -21,6 +22,11 @@ movdqu [esp-32], xmm2 movdqu [esp-16], xmm1 movdqu [esp], xmm0 +; fix stored esp. +mov ecx, [esp+192] +add ecx, 8 +mov [esp+192], ecx + ; call destination push esp call [destination] @@ -44,6 +50,7 @@ pop ecx pop ebx pop eax pop ebp +lea esp, [esp+4] ; skip original esp pop esp ret diff --git a/src/mid_hook.x86_64.asm b/src/mid_hook.x86_64.asm index 148e177..dfdf821 100644 --- a/src/mid_hook.x86_64.asm +++ b/src/mid_hook.x86_64.asm @@ -2,7 +2,8 @@ bits 64 ; save context push qword [rel trampoline] -push rsp +push rsp ; push trampoline rsp +push rsp ; push original rsp (this gets fixed later) push rbp push rax push rbx @@ -37,6 +38,11 @@ movdqu [rsp-32], xmm2 movdqu [rsp-16], xmm1 movdqu [rsp], xmm0 +; fix stored rsp. +mov rcx, [rsp+384] +add rcx, 16 +mov [rsp+384], rcx + ; set destination parameter lea rcx, [rsp] @@ -85,6 +91,7 @@ pop rcx pop rbx pop rax pop rbp +lea rsp, [rsp+8] ; skip original rsp pop rsp ret