From 3e0e14091acbbfe8e533a7c9b2421b4285f7b252 Mon Sep 17 00:00:00 2001 From: alk <45172705+altalk23@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:52:07 +0300 Subject: [PATCH] Cleanup (#18) * tiny amounts of cleanup (lots) --- .github/workflows/build.yml | 2 +- .../tulip/platform/MacosIntelConvention.hpp | 29 ++ include/tulip/platform/PlatformConvention.hpp | 3 + src/CMakeLists.txt | 1 + src/Handler.cpp | 19 +- src/Handler.hpp | 2 - src/Main.cpp | 4 + src/assembler/ArmV7Assembler.cpp | 2 - src/assembler/BaseAssembler.hpp | 1 + src/assembler/X64Assembler.cpp | 12 + src/assembler/X64Assembler.hpp | 5 + src/assembler/X86Assembler.cpp | 17 +- src/assembler/X86Assembler.hpp | 5 + src/convention/MacosIntelConvention.cpp | 83 ++++++ src/convention/Windows32Convention.cpp | 1 - src/convention/Windows64Convention.cpp | 62 +++- src/generator/ArmV7Generator.cpp | 62 ++-- src/generator/ArmV7Generator.hpp | 4 +- src/generator/ArmV8Generator.cpp | 58 ++-- src/generator/ArmV8Generator.hpp | 4 +- src/generator/Generator.cpp | 28 +- src/generator/Generator.hpp | 17 +- src/generator/X64Generator.cpp | 266 +++++++++++------- src/generator/X64Generator.hpp | 13 +- src/generator/X86Generator.cpp | 92 +++--- src/generator/X86Generator.hpp | 9 +- src/target/DarwinTarget.cpp | 1 - src/target/MacosIntelTarget.cpp | 4 +- src/target/MacosIntelTarget.hpp | 2 +- src/target/MacosM1Target.cpp | 4 +- src/target/MacosM1Target.hpp | 2 +- src/target/PosixArmV7Target.cpp | 4 +- src/target/PosixArmV7Target.hpp | 2 +- src/target/PosixArmV8Target.cpp | 4 +- src/target/PosixArmV8Target.hpp | 2 +- src/target/Target.hpp | 2 +- src/target/Windows32Target.cpp | 4 +- src/target/Windows32Target.hpp | 2 +- src/target/Windows64Target.cpp | 4 +- src/target/Windows64Target.hpp | 2 +- test/CallingConventions.cpp | 1 - 41 files changed, 545 insertions(+), 296 deletions(-) create mode 100644 include/tulip/platform/MacosIntelConvention.hpp create mode 100644 src/convention/MacosIntelConvention.cpp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ea2000..4ed0159 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,7 @@ jobs: - name: 'macOS' id: mac - os: macos-latest + os: macos-12 build_tests: true extra_flags: "-DCMAKE_BUILD_TYPE=Debug" out_paths: './build/src/libTulipHook.a' diff --git a/include/tulip/platform/MacosIntelConvention.hpp b/include/tulip/platform/MacosIntelConvention.hpp new file mode 100644 index 0000000..aff5cb5 --- /dev/null +++ b/include/tulip/platform/MacosIntelConvention.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "../Platform.hpp" + +#if defined(TULIP_HOOK_MACOS) && defined(TULIP_HOOK_X64) + +#include "../CallingConvention.hpp" + +#include +#include + +namespace tulip::hook { + class AbstractFunction; + + class TULIP_HOOK_DLL SystemVConvention : public CallingConvention { + public: + ~SystemVConvention() override; + + void generateDefaultCleanup(BaseAssembler& a, AbstractFunction const& function) override; + void generateIntoDefault(BaseAssembler& a, AbstractFunction const& function) override; + void generateIntoOriginal(BaseAssembler& a, AbstractFunction const& function) override; + void generateOriginalCleanup(BaseAssembler& a, AbstractFunction const& function) override; + bool needsWrapper(AbstractFunction const& function) const override; + + static std::shared_ptr create(); + }; +} + +#endif diff --git a/include/tulip/platform/PlatformConvention.hpp b/include/tulip/platform/PlatformConvention.hpp index b50090a..391bb2c 100644 --- a/include/tulip/platform/PlatformConvention.hpp +++ b/include/tulip/platform/PlatformConvention.hpp @@ -2,10 +2,13 @@ #include "DefaultConvention.hpp" #include "Windows32Convention.hpp" #include "Windows64Convention.hpp" +#include "MacosIntelConvention.hpp" namespace tulip::hook { #if defined(TULIP_HOOK_WINDOWS) && defined(TULIP_HOOK_X86) using PlatformConvention = CdeclConvention; +#elif defined(TULIP_HOOK_MACOS) && defined(TULIP_HOOK_X64) + using PlatformConvention = SystemVConvention; #else using PlatformConvention = DefaultConvention; #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b9f2118..bf220a5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ elseif(APPLE) assembler/X86Assembler.cpp assembler/X64Assembler.cpp assembler/ArmV8Assembler.cpp + convention/MacosIntelConvention.cpp generator/X86Generator.cpp generator/X64Generator.cpp generator/ArmV8Generator.cpp diff --git a/src/Handler.cpp b/src/Handler.cpp index cf1f3cf..ed59413 100644 --- a/src/Handler.cpp +++ b/src/Handler.cpp @@ -6,7 +6,6 @@ #include "target/PlatformTarget.hpp" #include -#include #include using namespace tulip::hook; @@ -22,21 +21,10 @@ Result> Handler::create(void* address, HandlerMetadata if (!ret->m_content) { return Err("Failed to allocate HandlerContent"); } - // std::cout << std::hex << "m_content: " << (void*)ret->m_content << std::endl; TULIP_HOOK_UNWRAP_INTO(ret->m_handler, Target::get().allocateArea(0x300)); - // std::cout << std::hex << "m_handler: " << (void*)ret->m_handler << std::endl; - TULIP_HOOK_UNWRAP_INTO(ret->m_trampoline, Target::get().allocateArea(0x100)); - auto wrapperMetadata = WrapperMetadata{ - .m_convention = metadata.m_convention, - .m_abstract = metadata.m_abstract, - }; - TULIP_HOOK_UNWRAP_INTO(auto trampolineWrap, Wrapper::get().createWrapper(ret->m_trampoline, wrapperMetadata)); - ret->m_wrapped = trampolineWrap; - // std::cout << std::hex << "m_trampoline: " << (void*)ret->m_trampoline << std::endl; - return Ok(std::move(ret)); } @@ -46,7 +34,7 @@ Result<> Handler::init() { // printf("func addr: 0x%" PRIx64 "\n", (uint64_t)m_address); auto generator = - Target::get().getHandlerGenerator(m_address, m_trampoline, m_handler, m_content, m_wrapped, m_metadata); + Target::get().getHandlerGenerator(m_address, m_trampoline, m_handler, m_content, m_metadata); TULIP_HOOK_UNWRAP(generator->generateHandler()); @@ -57,8 +45,7 @@ Result<> Handler::init() { auto address = reinterpret_cast(Target::get().getRealPtr(m_address)); m_originalBytes.insert(m_originalBytes.begin(), address, address + target); - TULIP_HOOK_UNWRAP_INTO(auto trampolineOffset, generator->relocateOriginal(target)); - TULIP_HOOK_UNWRAP(generator->generateTrampoline(trampolineOffset)); + TULIP_HOOK_UNWRAP(generator->generateTrampoline(target)); this->addOriginal(); @@ -69,7 +56,7 @@ void Handler::addOriginal() { auto metadata = HookMetadata{ .m_priority = INT32_MAX, }; - static_cast(this->createHook(Target::get().getRealPtrAs(m_wrapped, m_address), metadata)); + static_cast(this->createHook(Target::get().getRealPtrAs(m_trampoline, m_address), metadata)); } HookHandle Handler::createHook(void* address, HookMetadata m_metadata) { diff --git a/src/Handler.hpp b/src/Handler.hpp index 304e160..21ba61a 100644 --- a/src/Handler.hpp +++ b/src/Handler.hpp @@ -31,8 +31,6 @@ namespace tulip::hook { void* m_trampoline = nullptr; size_t m_trampolineSize = 0; - void* m_wrapped = nullptr; - void* m_handler = nullptr; size_t m_handlerSize = 0; diff --git a/src/Main.cpp b/src/Main.cpp index 7314052..1fd9ef8 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -61,6 +61,10 @@ std::shared_ptr tulip::hook::createConvention(TulipConvention #endif case TulipConvention::Default: default: +#if defined(TULIP_HOOK_MACOS) && defined(TULIP_HOOK_X64) + return SystemVConvention::create(); +#else return DefaultConvention::create(); +#endif } } diff --git a/src/assembler/ArmV7Assembler.cpp b/src/assembler/ArmV7Assembler.cpp index 4ee632c..e4ef3f5 100644 --- a/src/assembler/ArmV7Assembler.cpp +++ b/src/assembler/ArmV7Assembler.cpp @@ -1,7 +1,5 @@ #include "ArmV7Assembler.hpp" -#include - using namespace tulip::hook; ArmV7Assembler::ArmV7Assembler(int64_t baseAddress) : diff --git a/src/assembler/BaseAssembler.hpp b/src/assembler/BaseAssembler.hpp index 5991a43..32dca0b 100644 --- a/src/assembler/BaseAssembler.hpp +++ b/src/assembler/BaseAssembler.hpp @@ -19,6 +19,7 @@ namespace tulip::hook { std::vector m_buffer; std::unordered_map m_labels; std::vector m_labelUpdates; + std::vector m_absoluteLabelUpdates; BaseAssembler(int64_t baseAddress); BaseAssembler(BaseAssembler const&) = delete; diff --git a/src/assembler/X64Assembler.cpp b/src/assembler/X64Assembler.cpp index 231bfdc..9b62c6c 100644 --- a/src/assembler/X64Assembler.cpp +++ b/src/assembler/X64Assembler.cpp @@ -53,6 +53,10 @@ void X64Assembler::updateLabels() { for (auto const& update : m_labelUpdates) { this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4); } + // absolute is not absolute in 64 bit + for (auto const& update : m_absoluteLabelUpdates) { + this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4); + } } using enum X64Register; @@ -110,6 +114,14 @@ void X64Assembler::call(X64Register reg) { X86Assembler::call(x86reg(reg)); } +void X64Assembler::call(int64_t address) { + X86Assembler::call(address); +} + +void X64Assembler::call(std::string const& label) { + X86Assembler::call(label); +} + void X64Assembler::callip(std::string const& label) { this->write8(0xff); this->write8(0x15); diff --git a/src/assembler/X64Assembler.hpp b/src/assembler/X64Assembler.hpp index 6e28b92..3a369c3 100644 --- a/src/assembler/X64Assembler.hpp +++ b/src/assembler/X64Assembler.hpp @@ -43,6 +43,9 @@ namespace tulip::hook { inline X64Pointer operator+(X64Register reg, int32_t offset) { return X64Pointer(reg, offset); } + inline X64Pointer operator-(X64Register reg, int32_t offset) { + return X64Pointer(reg, -offset); + } // Use this to easily express a X64Pointer, like so: // RegMem64 m; @@ -77,6 +80,8 @@ namespace tulip::hook { void jmpip(std::string const& label); void call(X64Register reg); + void call(int64_t address); + void call(std::string const& label); void callip(std::string const& label); void movsd(X64Register reg, X64Pointer ptr); diff --git a/src/assembler/X86Assembler.cpp b/src/assembler/X86Assembler.cpp index fba9b72..6919898 100644 --- a/src/assembler/X86Assembler.cpp +++ b/src/assembler/X86Assembler.cpp @@ -20,8 +20,16 @@ void X86Assembler::label32(std::string const& name) { this->write32(0); } +void X86Assembler::abslabel32(std::string const& name) { + m_absoluteLabelUpdates.push_back({this->currentAddress(), name, 4}); + this->write32(0); +} + void X86Assembler::updateLabels() { for (auto const& update : m_labelUpdates) { + this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4); + } + for (auto const& update : m_absoluteLabelUpdates) { this->rewrite32(update.m_address, m_labels[update.m_name]); } } @@ -128,6 +136,11 @@ void X86Assembler::call(X86Register reg) { this->encodeModRM(reg, 2); } +void X86Assembler::call(std::string const& label) { + this->write8(0xE8); + this->label32(label); +} + void X86Assembler::movsd(X86Register reg, X86Pointer ptr) { this->write8(0xF2); this->write8(0x0F); @@ -171,7 +184,7 @@ void X86Assembler::movaps(X86Pointer ptr, X86Register reg) { void X86Assembler::lea(X86Register reg, std::string const& label) { this->write8(0x8D); this->write8(0x05 | regIdx(reg) << 3); - this->label32(label); + this->abslabel32(label); } void X86Assembler::mov(X86Register reg, int32_t value) { @@ -197,7 +210,7 @@ void X86Assembler::mov(X86Register dst, X86Register src) { void X86Assembler::mov(X86Register reg, std::string const& label) { this->write8(0x8B); this->write8(0x05 | regIdx(reg) << 3); - this->label32(label); + this->abslabel32(label); } void X86Assembler::fstps(X86Pointer ptr) { diff --git a/src/assembler/X86Assembler.hpp b/src/assembler/X86Assembler.hpp index 3440a1f..a5947ac 100644 --- a/src/assembler/X86Assembler.hpp +++ b/src/assembler/X86Assembler.hpp @@ -35,6 +35,9 @@ namespace tulip::hook { inline X86Pointer operator+(X86Register reg, int32_t offset) { return X86Pointer(reg, offset); } + inline X86Pointer operator-(X86Register reg, int32_t offset) { + return X86Pointer(reg, -offset); + } // Use this to easily express a X86Pointer, like so: // RegMem32 m; @@ -74,6 +77,7 @@ namespace tulip::hook { ~X86Assembler(); void label32(std::string const& name); + void abslabel32(std::string const& name); void updateLabels() override; void nop(); @@ -95,6 +99,7 @@ namespace tulip::hook { void call(X86Register reg); void call(int64_t value); + void call(std::string const& label); void movsd(X86Register reg, X86Pointer ptr); void movsd(X86Pointer ptr, X86Register reg); diff --git a/src/convention/MacosIntelConvention.cpp b/src/convention/MacosIntelConvention.cpp new file mode 100644 index 0000000..ff06f9c --- /dev/null +++ b/src/convention/MacosIntelConvention.cpp @@ -0,0 +1,83 @@ +#include + +#if defined(TULIP_HOOK_MACOS) && defined(TULIP_HOOK_X64) + +#include +#include +#include "../assembler/X64Assembler.hpp" + +using namespace tulip::hook; + +namespace { + size_t getStackParamSize(AbstractFunction const& function) { + size_t stackParamSize = 0; + int xmmCount = 0; + int gprCount = 0; + if (function.m_return.m_kind == AbstractTypeKind::Other && function.m_return.m_size > 16) { + gprCount += 1; + } + for (auto& param : function.m_parameters) { + if (param.m_kind == AbstractTypeKind::FloatingPoint) { + if (xmmCount < 8) { + xmmCount++; + } else { + stackParamSize += 8; + } + } else { + if (gprCount < 6) { + gprCount++; + } else { + stackParamSize += 8; + } + } + } + return stackParamSize; + } +} + +SystemVConvention::~SystemVConvention() {} + +void SystemVConvention::generateDefaultCleanup(BaseAssembler& a_, AbstractFunction const& function) { + size_t stackParamSize = getStackParamSize(function); + if (stackParamSize > 0) { + auto& a = static_cast(a_); + using enum X64Register; + auto const paddedSize = (stackParamSize % 16) ? stackParamSize + 8 : stackParamSize; + a.add(RSP, paddedSize); + } +} + +// used to move the stack values to the correct places + +void SystemVConvention::generateIntoDefault(BaseAssembler& a_, AbstractFunction const& function) { + size_t stackParamSize = getStackParamSize(function); + if (stackParamSize > 0) { + auto& a = static_cast(a_); + using enum X64Register; + RegMem64 m; + auto const paddedSize = (stackParamSize % 16) ? stackParamSize + 8 : stackParamSize; + a.sub(RSP, paddedSize); + int stackOffset = 0; + + for (auto i = 0; i < stackParamSize; i += 8) { + a.mov(RAX, m[RBP + (16 + i)]); + a.mov(m[RSP + i], RAX); + } + } +} + +void SystemVConvention::generateIntoOriginal(BaseAssembler& a_, AbstractFunction const& function) { +} + +void SystemVConvention::generateOriginalCleanup(BaseAssembler& a_, AbstractFunction const& function) { +} + +bool SystemVConvention::needsWrapper(AbstractFunction const& function) const { + return false; +} + +std::shared_ptr SystemVConvention::create() { + return std::make_shared(); +} + +#endif \ No newline at end of file diff --git a/src/convention/Windows32Convention.cpp b/src/convention/Windows32Convention.cpp index fffc4be..76685da 100644 --- a/src/convention/Windows32Convention.cpp +++ b/src/convention/Windows32Convention.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include diff --git a/src/convention/Windows64Convention.cpp b/src/convention/Windows64Convention.cpp index 7d5bb6a..86c1fb2 100644 --- a/src/convention/Windows64Convention.cpp +++ b/src/convention/Windows64Convention.cpp @@ -8,10 +8,43 @@ using namespace tulip::hook; +namespace { + size_t getStackParamSize(AbstractFunction const& function) { + size_t stackParamSize = 0; + int xmmCount = 0; + int gprCount = 0; + if (function.m_return.m_kind == AbstractTypeKind::Other) { + gprCount += 1; + } + for (auto& param : function.m_parameters) { + if (param.m_kind == AbstractTypeKind::FloatingPoint) { + if (xmmCount < 4) { + xmmCount++; + } else { + stackParamSize += 8; + } + } else { + if (gprCount < 4) { + gprCount++; + } else { + stackParamSize += 8; + } + } + } + return stackParamSize; + } +} + ThiscallConvention::~ThiscallConvention() {} -void ThiscallConvention::generateDefaultCleanup(BaseAssembler& a, AbstractFunction const& function) { - static_cast(a).ret(); +void ThiscallConvention::generateDefaultCleanup(BaseAssembler& a_, AbstractFunction const& function) { + size_t stackParamSize = getStackParamSize(function); + if (stackParamSize > 0) { + auto& a = static_cast(a_); + using enum X64Register; + auto const paddedSize = (stackParamSize % 16) ? stackParamSize + 8 : stackParamSize; + a.add(RSP, paddedSize); + } } // Member functions deal with struct return differently, since in the windows x64 convention @@ -25,23 +58,38 @@ void ThiscallConvention::generateDefaultCleanup(BaseAssembler& a, AbstractFuncti // so to undo this we just swap the first two parameters (RCX and RDX). void ThiscallConvention::generateIntoDefault(BaseAssembler& a_, AbstractFunction const& function) { + auto& a = static_cast(a_); + using enum X64Register; + RegMem64 m; + if (function.m_return.m_kind == AbstractTypeKind::Other) { - auto& a = static_cast(a_); - using enum X64Register; a.xchg(RCX, RDX); } + + size_t stackParamSize = getStackParamSize(function); + if (stackParamSize > 0) { + auto const paddedSize = (stackParamSize % 16) ? stackParamSize + 8 : stackParamSize; + a.sub(RSP, paddedSize); + int stackOffset = 0; + + for (auto i = 0; i < stackParamSize; i += 8) { + a.mov(RAX, m[RBP + (32 + i)]); + a.mov(m[RSP + i], RAX); + } + } } void ThiscallConvention::generateIntoOriginal(BaseAssembler& a_, AbstractFunction const& function) { + auto& a = static_cast(a_); + using enum X64Register; + RegMem64 m; + if (function.m_return.m_kind == AbstractTypeKind::Other) { - auto& a = static_cast(a_); - using enum X64Register; a.xchg(RCX, RDX); } } void ThiscallConvention::generateOriginalCleanup(BaseAssembler& a, AbstractFunction const& function) { - static_cast(a).ret(); } bool ThiscallConvention::needsWrapper(AbstractFunction const& function) const { diff --git a/src/generator/ArmV7Generator.cpp b/src/generator/ArmV7Generator.cpp index 48eb6ab..a4e3321 100644 --- a/src/generator/ArmV7Generator.cpp +++ b/src/generator/ArmV7Generator.cpp @@ -6,8 +6,6 @@ #include #include -#include -#include using namespace tulip::hook; @@ -27,37 +25,6 @@ namespace { } } -Result ArmV7HandlerGenerator::relocateOriginal(uint64_t target) { - auto origin = new CodeMemBlock((uint64_t)Target::get().getRealPtr(m_address), target); - auto relocated = new CodeMemBlock(); - // idk about arm thumb stuff help me - auto originBuffer = m_address; - auto relocatedBuffer = m_trampoline; - - static thread_local std::string error; - error = ""; - - GenRelocateCodeAndBranch(originBuffer, relocatedBuffer, origin, relocated, +[](void* dest, void const* src, size_t size) { - auto res = Target::get().writeMemory(dest, src, size); - if (!res) { - error = res.error(); - } - }); - - if (!error.empty()) { - return Err(std::move(error)); - } - - if (relocated->size == 0) { - return Err("Failed to relocate original function"); - } - - return Ok(RelocateReturn{ - .m_trampolineOffset = (uint64_t)relocated->size, - .m_originalOffset = (uint64_t)origin->size, - }); -} - std::vector ArmV7HandlerGenerator::handlerBytes(uint64_t address) { ArmV7Assembler a((uint64_t)Target::get().getRealPtr((void*)address)); using enum ArmV7Register; @@ -138,12 +105,29 @@ std::vector ArmV7HandlerGenerator::intervenerBytes(uint64_t address) { return std::move(a.m_buffer); } -std::vector ArmV7HandlerGenerator::trampolineBytes(uint64_t address, size_t offset) { - // Dobby handles the creation of the trampoline - return {}; -} +Result<> ArmV7HandlerGenerator::generateTrampoline(uint64_t target) { + auto origin = new CodeMemBlock((uint64_t)Target::get().getRealPtr(m_address), target); + auto relocated = new CodeMemBlock(); + // idk about arm thumb stuff help me + auto originBuffer = m_address; + auto relocatedBuffer = m_trampoline; + + static thread_local std::string error; + error = ""; -Result<> ArmV7HandlerGenerator::generateTrampoline(RelocateReturn offsets) { - // Dobby handles the creation of the trampoline + GenRelocateCodeAndBranch(originBuffer, relocatedBuffer, origin, relocated, +[](void* dest, void const* src, size_t size) { + auto res = Target::get().writeMemory(dest, src, size); + if (!res) { + error = res.error(); + } + }); + + if (!error.empty()) { + return Err(std::move(error)); + } + + if (relocated->size == 0) { + return Err("Failed to relocate original function"); + } return Ok(); } diff --git a/src/generator/ArmV7Generator.hpp b/src/generator/ArmV7Generator.hpp index 43149a5..7a9ce32 100644 --- a/src/generator/ArmV7Generator.hpp +++ b/src/generator/ArmV7Generator.hpp @@ -10,12 +10,10 @@ namespace tulip::hook { public: using HandlerGenerator::HandlerGenerator; - Result<> generateTrampoline(RelocateReturn offsets) override; - Result relocateOriginal(uint64_t target) override; + Result<> generateTrampoline(uint64_t target) override; std::vector handlerBytes(uint64_t address) override; std::vector intervenerBytes(uint64_t address) override; - std::vector trampolineBytes(uint64_t address, size_t offset) override; }; class ArmV7WrapperGenerator : public WrapperGenerator { diff --git a/src/generator/ArmV8Generator.cpp b/src/generator/ArmV8Generator.cpp index 5240cd4..4b94cb0 100644 --- a/src/generator/ArmV8Generator.cpp +++ b/src/generator/ArmV8Generator.cpp @@ -24,36 +24,6 @@ namespace { } } -Result ArmV8HandlerGenerator::relocateOriginal(uint64_t target) { - auto origin = new CodeMemBlock(reinterpret_cast(m_address), target); - auto relocated = new CodeMemBlock(); - auto originBuffer = m_address; - auto relocatedBuffer = m_trampoline; - - static thread_local std::string error; - error = ""; - - GenRelocateCodeAndBranch(originBuffer, relocatedBuffer, origin, relocated, +[](void* dest, void const* src, size_t size) { - auto res = Target::get().writeMemory(dest, src, size); - if (!res) { - error = res.error(); - } - }); - - if (!error.empty()) { - return Err(std::move(error)); - } - - if (relocated->size == 0) { - return Err("Failed to relocate original function"); - } - - return Ok(RelocateReturn{ - .m_trampolineOffset = (uint64_t)relocated->size, - .m_originalOffset = (uint64_t)origin->size, - }); -} - std::vector ArmV8HandlerGenerator::handlerBytes(uint64_t address) { ArmV8Assembler a(address); using enum ArmV8Register; @@ -155,12 +125,28 @@ std::vector ArmV8HandlerGenerator::intervenerBytes(uint64_t address) { return std::move(a.m_buffer); } -std::vector ArmV8HandlerGenerator::trampolineBytes(uint64_t address, size_t offset) { - // Dobby handles the creation of the trampoline - return {}; -} +Result<> ArmV8HandlerGenerator::generateTrampoline(uint64_t target) { + auto origin = new CodeMemBlock(reinterpret_cast(m_address), target); + auto relocated = new CodeMemBlock(); + auto originBuffer = m_address; + auto relocatedBuffer = m_trampoline; -Result<> ArmV8HandlerGenerator::generateTrampoline(RelocateReturn offsets) { - // Dobby handles the creation of the trampoline + static thread_local std::string error; + error = ""; + + GenRelocateCodeAndBranch(originBuffer, relocatedBuffer, origin, relocated, +[](void* dest, void const* src, size_t size) { + auto res = Target::get().writeMemory(dest, src, size); + if (!res) { + error = res.error(); + } + }); + + if (!error.empty()) { + return Err(std::move(error)); + } + + if (relocated->size == 0) { + return Err("Failed to relocate original function"); + } return Ok(); } diff --git a/src/generator/ArmV8Generator.hpp b/src/generator/ArmV8Generator.hpp index 6ea13e3..5512389 100644 --- a/src/generator/ArmV8Generator.hpp +++ b/src/generator/ArmV8Generator.hpp @@ -10,12 +10,10 @@ namespace tulip::hook { public: using HandlerGenerator::HandlerGenerator; - Result<> generateTrampoline(RelocateReturn offsets) override; - Result relocateOriginal(uint64_t target) override; + Result<> generateTrampoline(uint64_t target) override; std::vector handlerBytes(uint64_t address) override; std::vector intervenerBytes(uint64_t address) override; - std::vector trampolineBytes(uint64_t address, size_t offset) override; }; class ArmV8WrapperGenerator : public WrapperGenerator { diff --git a/src/generator/Generator.cpp b/src/generator/Generator.cpp index 8ad45ff..8d1a2f2 100644 --- a/src/generator/Generator.cpp +++ b/src/generator/Generator.cpp @@ -5,13 +5,12 @@ using namespace tulip::hook; HandlerGenerator::HandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) : m_address(address), m_trampoline(trampoline), m_handler(handler), m_content(content), - m_wrapped(wrapped), m_metadata(metadata) {} WrapperGenerator::WrapperGenerator(void* address, WrapperMetadata const& metadata) : @@ -34,15 +33,34 @@ Result> HandlerGenerator::generateIntervener() { return Ok(std::move(encode)); } -Result<> HandlerGenerator::generateTrampoline(RelocateReturn offsets) { - auto address = reinterpret_cast(m_trampoline) + offsets.m_trampolineOffset; +Result<> HandlerGenerator::generateTrampoline(uint64_t target) { + TULIP_HOOK_UNWRAP_INTO(auto offsets, this->relocatedBytes(reinterpret_cast(m_trampoline), target)); + + auto address = reinterpret_cast(m_trampoline) + offsets.m_relocatedBytes.size(); auto encode = this->trampolineBytes(address, offsets.m_originalOffset); - TULIP_HOOK_UNWRAP(Target::get().writeMemory(reinterpret_cast(address), encode.data(), encode.size())); + std::vector merge; + merge.insert(merge.end(), offsets.m_relocatedBytes.begin(), offsets.m_relocatedBytes.end()); + merge.insert(merge.end(), encode.begin(), encode.end()); + + TULIP_HOOK_UNWRAP(Target::get().writeMemory(m_trampoline, merge.data(), merge.size())); return Ok(); } +std::vector HandlerGenerator::handlerBytes(uint64_t address) { + return std::vector(); +} +std::vector HandlerGenerator::intervenerBytes(uint64_t address) { + return std::vector(); +} +std::vector HandlerGenerator::trampolineBytes(uint64_t address, size_t offset) { + return std::vector(); +} +Result HandlerGenerator::relocatedBytes(uint64_t base, uint64_t target) { + return Ok(HandlerGenerator::RelocateReturn()); +} + Result WrapperGenerator::generateWrapper() { return Ok(m_address); // only windows needs the wrapper } diff --git a/src/generator/Generator.hpp b/src/generator/Generator.hpp index 998a1f5..3fa0109 100644 --- a/src/generator/Generator.hpp +++ b/src/generator/Generator.hpp @@ -13,11 +13,10 @@ namespace tulip::hook { void* const m_trampoline; void* const m_handler; void* const m_content; - void* const m_wrapped; HandlerMetadata const m_metadata; HandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ); virtual ~HandlerGenerator() = default; @@ -26,16 +25,16 @@ namespace tulip::hook { virtual Result> generateIntervener(); struct RelocateReturn { - uint64_t m_trampolineOffset; - uint64_t m_originalOffset; + std::vector m_relocatedBytes; + int64_t m_originalOffset; }; - virtual Result<> generateTrampoline(RelocateReturn offsets); - virtual Result relocateOriginal(uint64_t target) = 0; + virtual Result<> generateTrampoline(uint64_t target); - virtual std::vector handlerBytes(uint64_t address) = 0; - virtual std::vector intervenerBytes(uint64_t address) = 0; - virtual std::vector trampolineBytes(uint64_t address, size_t offset) = 0; + virtual std::vector handlerBytes(uint64_t address); + virtual std::vector intervenerBytes(uint64_t address); + virtual std::vector trampolineBytes(uint64_t address, size_t offset); + virtual Result relocatedBytes(uint64_t base, uint64_t target); }; class WrapperGenerator { diff --git a/src/generator/X64Generator.cpp b/src/generator/X64Generator.cpp index 4411e5e..46d8935 100644 --- a/src/generator/X64Generator.cpp +++ b/src/generator/X64Generator.cpp @@ -5,50 +5,26 @@ #include "../target/PlatformTarget.hpp" #include -#include using namespace tulip::hook; namespace { - void* TULIP_HOOK_DEFAULT_CONV preHandler(HandlerContent* content, void* originalReturn) { + void* TULIP_HOOK_DEFAULT_CONV preHandler(HandlerContent* content) { Handler::incrementIndex(content); auto ret = Handler::getNextFunction(content); - Handler::pushData(originalReturn); - return ret; } - void* TULIP_HOOK_DEFAULT_CONV postHandler() { - auto ret = Handler::popData(); + void TULIP_HOOK_DEFAULT_CONV postHandler() { Handler::decrementIndex(); - return ret; } } -std::vector X64HandlerGenerator::handlerBytes(uint64_t address) { - X64Assembler a(address); - RegMem64 m; +size_t X64HandlerGenerator::preserveRegisters(X64Assembler& a) { using enum X64Register; - -#ifdef TULIP_HOOK_WINDOWS - constexpr auto SCRATCH = RAX; - constexpr auto FIRST_PARAM = RCX; - constexpr auto SECOND_PARAM = RDX; -#else - constexpr auto SCRATCH = RAX; - constexpr auto FIRST_PARAM = RDI; - constexpr auto SECOND_PARAM = RSI; -#endif - - for (size_t i = 0; i < 8; ++i) { - a.nop(); - } - - m_metadata.m_convention->generateIntoDefault(a, m_metadata.m_abstract); - - // preserve registers + RegMem64 m; #ifdef TULIP_HOOK_WINDOWS - constexpr auto PRESERVE_SIZE = 0x78; + constexpr auto PRESERVE_SIZE = 0x70; a.sub(RSP, PRESERVE_SIZE); a.mov(m[RSP + 0x58], R9); @@ -60,7 +36,7 @@ std::vector X64HandlerGenerator::handlerBytes(uint64_t address) { a.movaps(m[RSP + 0x10], XMM1); a.movaps(m[RSP + 0x00], XMM0); #else - constexpr auto PRESERVE_SIZE = 0xb8; + constexpr auto PRESERVE_SIZE = 0xc0; a.sub(RSP, PRESERVE_SIZE); a.mov(m[RSP + 0xa8], R9); @@ -78,23 +54,11 @@ std::vector X64HandlerGenerator::handlerBytes(uint64_t address) { a.movaps(m[RSP + 0x10], XMM1); a.movaps(m[RSP + 0x00], XMM0); #endif - - // preserve the original return - a.mov(SCRATCH, m[RSP + PRESERVE_SIZE]); - - // set the new return - a.lea(FIRST_PARAM, "handlerCont"); - a.mov(m[RSP + PRESERVE_SIZE], FIRST_PARAM); - - // set the parameters - a.mov(FIRST_PARAM, "content"); - a.mov(SECOND_PARAM, SCRATCH); - - // call the pre handler, incrementing - a.mov(SCRATCH, "handlerPre"); - a.call(SCRATCH); - - // recover registers + return PRESERVE_SIZE; +} +void X64HandlerGenerator::restoreRegisters(X64Assembler& a, size_t size) { + using enum X64Register; + RegMem64 m; #ifdef TULIP_HOOK_WINDOWS a.movaps(XMM0, m[RSP + 0x00]); a.movaps(XMM1, m[RSP + 0x10]); @@ -105,7 +69,7 @@ std::vector X64HandlerGenerator::handlerBytes(uint64_t address) { a.mov(R8, m[RSP + 0x50]); a.mov(R9, m[RSP + 0x58]); - a.add(RSP, PRESERVE_SIZE); + a.add(RSP, size); #else a.movaps(XMM0, m[RSP + 0x00]); a.movaps(XMM1, m[RSP + 0x10]); @@ -122,40 +86,101 @@ std::vector X64HandlerGenerator::handlerBytes(uint64_t address) { a.mov(R8, m[RSP + 0xa0]); a.mov(R9, m[RSP + 0xa8]); - a.add(RSP, PRESERVE_SIZE); + a.add(RSP, size); #endif +} - // call the func - a.jmp(SCRATCH); +size_t X64HandlerGenerator::preserveReturnRegisters(X64Assembler& a) { + using enum X64Register; + RegMem64 m; +#ifdef TULIP_HOOK_WINDOWS + constexpr auto PRESERVE_SIZE = 0x20; + a.sub(RSP, PRESERVE_SIZE); - a.label("handlerCont"); + a.movaps(m[RSP + 0x00], XMM0); + a.mov(RSP + 0x10, RAX); +#else + constexpr auto PRESERVE_SIZE = 0x30; + a.sub(RSP, PRESERVE_SIZE); - a.sub(RSP, 0x8); + a.movaps(m[RSP + 0x00], XMM0); + a.movaps(m[RSP + 0x10], XMM1); + a.mov(RSP + 0x20, RAX); + a.mov(RSP + 0x28, RDX); +#endif + return PRESERVE_SIZE; +} +void X64HandlerGenerator::restoreReturnRegisters(X64Assembler& a, size_t size) { + using enum X64Register; + RegMem64 m; +#ifdef TULIP_HOOK_WINDOWS + a.mov(RAX, m[RSP + 0x10]); + a.movaps(XMM0, m[RSP + 0x00]); - // preserve the return values - a.sub(RSP, 0x38); + a.add(RSP, size); +#else + a.mov(RDX, m[RSP + 0x28]); + a.mov(RAX, m[RSP + 0x20]); + a.movaps(XMM1, m[RSP + 0x10]); + a.movaps(XMM0, m[RSP + 0x00]); - a.mov(m[RSP + 0x28], RDX); - a.mov(m[RSP + 0x20], RAX); - a.movaps(m[RSP + 0x10], XMM1); - a.movaps(m[RSP + 0x00], XMM0); + a.add(RSP, size); +#endif +} - // call the post handler, decrementing - a.mov(SCRATCH, "handlerPost"); - a.call(SCRATCH); +std::vector X64HandlerGenerator::handlerBytes(uint64_t address) { + X64Assembler a(address); + RegMem64 m; + using enum X64Register; - // recover the original return - a.mov(m[RSP + 0x38], SCRATCH); +#ifdef TULIP_HOOK_WINDOWS + constexpr auto FIRST_PARAM = RCX; +#else + constexpr auto FIRST_PARAM = RDI; +#endif - // recover the return values - a.movaps(XMM0, m[RSP + 0x00]); - a.movaps(XMM1, m[RSP + 0x10]); - a.mov(RAX, m[RSP + 0x20]); - a.mov(RDX, m[RSP + 0x28]); + for (size_t i = 0; i < 8; ++i) { + a.nop(); + } + + a.push(RBP); + a.mov(RBP, RSP); + a.sub(RSP, 0x10); + // preserve registers + const auto preservedSize = preserveRegisters(a); + + // set the parameters + a.mov(FIRST_PARAM, "content"); + + // call the pre handler, incrementing + a.callip("handlerPre"); + + a.mov(m[RBP - 0x10], RAX); + + // recover registers + restoreRegisters(a, preservedSize); + + // call the func + m_metadata.m_convention->generateIntoDefault(a, m_metadata.m_abstract); + + a.mov(RAX, m[RBP - 0x10]); + // a.int3(); + a.call(RAX); + // // a.int3(); + m_metadata.m_convention->generateDefaultCleanup(a, m_metadata.m_abstract); + + // preserve the return values + const auto returnPreservedSize = preserveReturnRegisters(a); - a.add(RSP, 0x38); + // call the post handler, decrementing + a.callip("handlerPost"); + + // recover the return values + restoreReturnRegisters(a, returnPreservedSize); // done! + a.mov(RSP, RBP); + a.pop(RBP); a.ret(); a.label("handlerPre"); @@ -193,26 +218,6 @@ std::vector X64HandlerGenerator::intervenerBytes(uint64_t address) { return std::move(a.m_buffer); } -std::vector X64HandlerGenerator::trampolineBytes(uint64_t address, size_t offset) { - X64Assembler a(address); - RegMem64 m; - using enum X64Register; - - auto difference = reinterpret_cast(m_address) - static_cast(address) - 5 + offset; - - if (difference <= 0x7fffffffll && difference >= -0x80000000ll) { - a.jmp(reinterpret_cast(m_address) + offset); - } - else { - a.jmpip("handler"); - a.label("handler"); - a.write64(reinterpret_cast(m_address) + offset); - - a.updateLabels(); - } - - return std::move(a.m_buffer); -} Result<> X64HandlerGenerator::relocateRIPInstruction(cs_insn* insn, uint8_t* buffer, uint64_t& trampolineAddress, uint64_t& originalAddress, int64_t disp) { auto const id = insn->id; @@ -305,15 +310,24 @@ std::vector X64WrapperGenerator::wrapperBytes(uint64_t address) { X64Assembler a(address); using enum X64Register; + a.push(RBP); + a.mov(RBP, RSP); + m_metadata.m_convention->generateIntoOriginal(a, m_metadata.m_abstract); - a.sub(RSP, 8); - a.mov(RAX, "address"); - a.call(RAX); - a.add(RSP, 8); + auto difference = a.currentAddress() - reinterpret_cast(m_address) + 5; + if (difference <= 0x7fffffffll && difference >= -0x80000000ll) { + a.call(reinterpret_cast(m_address)); + } + else { + a.callip("address"); + } m_metadata.m_convention->generateOriginalCleanup(a, m_metadata.m_abstract); + a.pop(RBP); + a.ret(); + a.label("address"); a.write64(reinterpret_cast(m_address)); @@ -322,25 +336,67 @@ std::vector X64WrapperGenerator::wrapperBytes(uint64_t address) { return std::move(a.m_buffer); } -std::vector X64WrapperGenerator::reverseWrapperBytes(uint64_t address) { - X64Assembler a(address); +// std::vector X64WrapperGenerator::reverseWrapperBytes(uint64_t address) { +// X64Assembler a(address); +// using enum X64Register; + +// m_metadata.m_convention->generateIntoDefault(a, m_metadata.m_abstract); + +// a.mov(RAX, "address"); +// a.call(RAX); + +// m_metadata.m_convention->generateDefaultCleanup(a, m_metadata.m_abstract); + +// a.label("address"); +// a.write64(reinterpret_cast(m_address)); + +// a.updateLabels(); + +// return std::move(a.m_buffer); +// } + +Result<> X64HandlerGenerator::generateTrampoline(uint64_t target) { + X64Assembler a(reinterpret_cast(m_trampoline)); using enum X64Register; - m_metadata.m_convention->generateIntoDefault(a, m_metadata.m_abstract); + if (m_metadata.m_convention->needsWrapper(m_metadata.m_abstract)) { + a.push(RBP); + a.mov(RBP, RSP); + m_metadata.m_convention->generateIntoOriginal(a, m_metadata.m_abstract); - a.sub(RSP, 8); - a.mov(RAX, "address"); - a.call(RAX); - a.add(RSP, 8); + a.call("relocated"); - m_metadata.m_convention->generateDefaultCleanup(a, m_metadata.m_abstract); + m_metadata.m_convention->generateOriginalCleanup(a, m_metadata.m_abstract); + a.pop(RBP); + a.ret(); + } - a.label("address"); - a.write64(reinterpret_cast(m_address)); + a.label("relocated"); + + TULIP_HOOK_UNWRAP_INTO(auto code, this->relocatedBytes(a.currentAddress(), target)); + + a.m_buffer.insert(a.m_buffer.end(), code.m_relocatedBytes.begin(), code.m_relocatedBytes.end()); + + auto difference = a.currentAddress() - reinterpret_cast(m_address) + 5 - code.m_originalOffset; + + if (difference <= 0x7fffffffll && difference >= -0x80000000ll) { + a.jmp(reinterpret_cast(m_address) + code.m_originalOffset); + } + else { + a.jmpip("handler"); + + a.label("handler"); + a.write64(reinterpret_cast(m_address) + code.m_originalOffset); + } a.updateLabels(); - return std::move(a.m_buffer); + auto codeSize = a.m_buffer.size(); + auto areaSize = (codeSize + (0x20 - codeSize) % 0x20); + + TULIP_HOOK_UNWRAP(Target::get().writeMemory(m_trampoline, a.m_buffer.data(), a.m_buffer.size())); + + return Ok(); } Result<> X64HandlerGenerator::relocateBranchInstruction(cs_insn* insn, uint8_t* buffer, uint64_t& trampolineAddress, uint64_t& originalAddress, int64_t targetAddress) { diff --git a/src/generator/X64Generator.hpp b/src/generator/X64Generator.hpp index 0fc821a..2b0876e 100644 --- a/src/generator/X64Generator.hpp +++ b/src/generator/X64Generator.hpp @@ -5,6 +5,7 @@ #include namespace tulip::hook { + class X64Assembler; class X64HandlerGenerator : public X86HandlerGenerator { public: @@ -12,10 +13,18 @@ namespace tulip::hook { std::vector handlerBytes(uint64_t address) override; std::vector intervenerBytes(uint64_t address) override; - std::vector trampolineBytes(uint64_t address, size_t offset) override; + + Result<> generateTrampoline(uint64_t target) override; Result<> relocateRIPInstruction(cs_insn* insn, uint8_t* buffer, uint64_t& trampolineAddress, uint64_t& originalAddress, int64_t disp) override; Result<> relocateBranchInstruction(cs_insn* insn, uint8_t* buffer, uint64_t& trampolineAddress, uint64_t& originalAddress, int64_t targetAddress) override; + + private: + size_t preserveRegisters(X64Assembler& a); + void restoreRegisters(X64Assembler& a, size_t size); + + size_t preserveReturnRegisters(X64Assembler& a); + void restoreReturnRegisters(X64Assembler& a, size_t size); }; class X64WrapperGenerator : public X86WrapperGenerator { @@ -23,6 +32,6 @@ namespace tulip::hook { using X86WrapperGenerator::X86WrapperGenerator; std::vector wrapperBytes(uint64_t address) override; - std::vector reverseWrapperBytes(uint64_t address) override; + // std::vector reverseWrapperBytes(uint64_t address) override; }; } diff --git a/src/generator/X86Generator.cpp b/src/generator/X86Generator.cpp index 12a15f5..98ec742 100644 --- a/src/generator/X86Generator.cpp +++ b/src/generator/X86Generator.cpp @@ -6,7 +6,6 @@ #include #include -#include using namespace tulip::hook; @@ -14,7 +13,6 @@ namespace { void* TULIP_HOOK_DEFAULT_CONV preHandler(HandlerContent* content) { Handler::incrementIndex(content); auto ret = Handler::getNextFunction(content); - return ret; } @@ -110,14 +108,6 @@ std::vector X86HandlerGenerator::intervenerBytes(uint64_t address) { return std::move(a.m_buffer); } -std::vector X86HandlerGenerator::trampolineBytes(uint64_t address, size_t offset) { - X86Assembler a(address); - - a.jmp(reinterpret_cast(m_address) + offset); - - return std::move(a.m_buffer); -} - std::vector X86WrapperGenerator::wrapperBytes(uint64_t address) { X86Assembler a(address); @@ -130,17 +120,17 @@ std::vector X86WrapperGenerator::wrapperBytes(uint64_t address) { return std::move(a.m_buffer); } -std::vector X86WrapperGenerator::reverseWrapperBytes(uint64_t address) { - X86Assembler a(address); +// std::vector X86WrapperGenerator::reverseWrapperBytes(uint64_t address) { +// X86Assembler a(address); - m_metadata.m_convention->generateIntoDefault(a, m_metadata.m_abstract); +// m_metadata.m_convention->generateIntoDefault(a, m_metadata.m_abstract); - a.call(reinterpret_cast(m_address)); +// a.call(reinterpret_cast(m_address)); - m_metadata.m_convention->generateDefaultCleanup(a, m_metadata.m_abstract); +// m_metadata.m_convention->generateDefaultCleanup(a, m_metadata.m_abstract); - return std::move(a.m_buffer); -} +// return std::move(a.m_buffer); +// } Result X86WrapperGenerator::generateWrapper() { if (!m_metadata.m_convention->needsWrapper(m_metadata.m_abstract)) { @@ -159,24 +149,52 @@ Result X86WrapperGenerator::generateWrapper() { return Ok(area); } -Result X86WrapperGenerator::generateReverseWrapper() { - if (!m_metadata.m_convention->needsWrapper(m_metadata.m_abstract)) { - return Ok(m_address); - } +// Result X86WrapperGenerator::generateReverseWrapper() { +// if (!m_metadata.m_convention->needsWrapper(m_metadata.m_abstract)) { +// return Ok(m_address); +// } - // this is silly, butt - auto codeSize = this->reverseWrapperBytes(0).size(); +// // this is silly, butt +// auto codeSize = this->reverseWrapperBytes(0).size(); +// auto areaSize = (codeSize + (0x20 - codeSize) % 0x20); + +// TULIP_HOOK_UNWRAP_INTO(auto area, Target::get().allocateArea(areaSize)); +// auto code = this->reverseWrapperBytes(reinterpret_cast(area)); + +// TULIP_HOOK_UNWRAP(Target::get().writeMemory(area, code.data(), codeSize)); + +// return Ok(area); +// } + +Result<> X86HandlerGenerator::generateTrampoline(uint64_t target) { + X86Assembler a(reinterpret_cast(m_trampoline)); + RegMem32 m; + using enum X86Register; + + m_metadata.m_convention->generateIntoOriginal(a, m_metadata.m_abstract); + a.call("relocated"); + m_metadata.m_convention->generateOriginalCleanup(a, m_metadata.m_abstract); + + a.label("relocated"); + + TULIP_HOOK_UNWRAP_INTO(auto code, this->relocatedBytes(a.currentAddress(), target)); + + a.m_buffer.insert(a.m_buffer.end(), code.m_relocatedBytes.begin(), code.m_relocatedBytes.end()); + + a.jmp(reinterpret_cast(m_address) + code.m_originalOffset); + + a.updateLabels(); + + auto codeSize = a.m_buffer.size(); auto areaSize = (codeSize + (0x20 - codeSize) % 0x20); - TULIP_HOOK_UNWRAP_INTO(auto area, Target::get().allocateArea(areaSize)); - auto code = this->reverseWrapperBytes(reinterpret_cast(area)); - TULIP_HOOK_UNWRAP(Target::get().writeMemory(area, code.data(), codeSize)); + TULIP_HOOK_UNWRAP(Target::get().writeMemory(m_trampoline, a.m_buffer.data(), a.m_buffer.size())); - return Ok(area); + return Ok(); } -Result X86HandlerGenerator::relocateOriginal(uint64_t target) { +Result X86HandlerGenerator::relocatedBytes(uint64_t baseAddress, uint64_t target) { // memcpy(m_trampoline, m_address, 32); TULIP_HOOK_UNWRAP_INTO(auto cs, Target::get().openCapstone()); @@ -185,23 +203,23 @@ Result X86HandlerGenerator::relocateOrigina auto insn = cs_malloc(cs); - uint64_t address = reinterpret_cast(m_trampoline); + uint64_t address = baseAddress; uint8_t const* code = reinterpret_cast(m_address); size_t size = 32; - auto difference = reinterpret_cast(m_trampoline) - reinterpret_cast(m_address); + auto difference = baseAddress - reinterpret_cast(m_address); auto targetAddress = address + target; auto originalAddress = reinterpret_cast(m_address); - auto trampolineAddress = reinterpret_cast(m_trampoline); - std::array buffer; + auto trampolineAddress = baseAddress; + std::array buffer; while (cs_disasm_iter(cs, &code, &size, &address, insn)) { if (insn->address >= targetAddress) { break; } - auto bufferOffset = trampolineAddress - reinterpret_cast(m_trampoline); + auto bufferOffset = trampolineAddress - baseAddress; TULIP_HOOK_UNWRAP(this->relocateInstruction(insn, buffer.data() + bufferOffset, trampolineAddress, originalAddress)); } @@ -210,12 +228,10 @@ Result X86HandlerGenerator::relocateOrigina Target::get().closeCapstone(); - auto bufferOffset = trampolineAddress - reinterpret_cast(m_trampoline); - TULIP_HOOK_UNWRAP(Target::get().writeMemory(m_trampoline, buffer.data(), bufferOffset)); - + auto bufferOffset = trampolineAddress - baseAddress; return Ok(RelocateReturn{ - .m_trampolineOffset = trampolineAddress - reinterpret_cast(m_trampoline), - .m_originalOffset = originalAddress - reinterpret_cast(m_address), + .m_relocatedBytes = std::vector(buffer.begin(), buffer.begin() + bufferOffset), + .m_originalOffset = static_cast(originalAddress - reinterpret_cast(m_address)), }); } diff --git a/src/generator/X86Generator.hpp b/src/generator/X86Generator.hpp index 156ab58..615abf9 100644 --- a/src/generator/X86Generator.hpp +++ b/src/generator/X86Generator.hpp @@ -11,11 +11,12 @@ namespace tulip::hook { public: using HandlerGenerator::HandlerGenerator; - Result relocateOriginal(uint64_t target) override; + Result relocatedBytes(uint64_t base, uint64_t target) override; std::vector handlerBytes(uint64_t address) override; std::vector intervenerBytes(uint64_t address) override; - std::vector trampolineBytes(uint64_t address, size_t offset) override; + + Result<> generateTrampoline(uint64_t target) override; virtual Result<> relocateInstruction(cs_insn* insn, uint8_t* buffer, uint64_t& trampolineAddress, uint64_t& originalAddress); virtual Result<> relocateRIPInstruction(cs_insn* insn, uint8_t* buffer, uint64_t& trampolineAddress, uint64_t& originalAddress, int64_t disp); @@ -27,10 +28,10 @@ namespace tulip::hook { using WrapperGenerator::WrapperGenerator; Result generateWrapper() override; - Result generateReverseWrapper() override; + // Result generateReverseWrapper() override; std::vector wrapperBytes(uint64_t address) override; - std::vector reverseWrapperBytes(uint64_t address) override; + // std::vector reverseWrapperBytes(uint64_t address) override; }; } diff --git a/src/target/DarwinTarget.cpp b/src/target/DarwinTarget.cpp index 34b9cdc..4af0f5d 100644 --- a/src/target/DarwinTarget.cpp +++ b/src/target/DarwinTarget.cpp @@ -11,7 +11,6 @@ using namespace tulip::hook; #include #include /* vm_allocate() */ #include -#include Result<> DarwinTarget::allocatePage() { kern_return_t status; diff --git a/src/target/MacosIntelTarget.cpp b/src/target/MacosIntelTarget.cpp index 6887be0..45adac6 100644 --- a/src/target/MacosIntelTarget.cpp +++ b/src/target/MacosIntelTarget.cpp @@ -23,9 +23,9 @@ Result MacosIntelTarget::openCapstone() { } std::unique_ptr MacosIntelTarget::getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) { - return std::make_unique(address, trampoline, handler, content, wrapped, metadata); + return std::make_unique(address, trampoline, handler, content, metadata); } std::unique_ptr MacosIntelTarget::getWrapperGenerator(void* address, WrapperMetadata const& metadata) { diff --git a/src/target/MacosIntelTarget.hpp b/src/target/MacosIntelTarget.hpp index 48cb874..a6959d2 100644 --- a/src/target/MacosIntelTarget.hpp +++ b/src/target/MacosIntelTarget.hpp @@ -15,7 +15,7 @@ namespace tulip::hook { Result openCapstone() override; std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) override; std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) override; }; diff --git a/src/target/MacosM1Target.cpp b/src/target/MacosM1Target.cpp index 309c092..b47f2c0 100644 --- a/src/target/MacosM1Target.cpp +++ b/src/target/MacosM1Target.cpp @@ -23,9 +23,9 @@ Result MacosM1Target::openCapstone() { } std::unique_ptr MacosM1Target::getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) { - return std::make_unique(address, trampoline, handler, content, wrapped, metadata); + return std::make_unique(address, trampoline, handler, content, metadata); } std::unique_ptr MacosM1Target::getWrapperGenerator(void* address, WrapperMetadata const& metadata) { diff --git a/src/target/MacosM1Target.hpp b/src/target/MacosM1Target.hpp index 6bdeca8..d721320 100644 --- a/src/target/MacosM1Target.hpp +++ b/src/target/MacosM1Target.hpp @@ -15,7 +15,7 @@ namespace tulip::hook { Result openCapstone() override; std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) override; std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) override; }; diff --git a/src/target/PosixArmV7Target.cpp b/src/target/PosixArmV7Target.cpp index a36ae2b..289fcbb 100644 --- a/src/target/PosixArmV7Target.cpp +++ b/src/target/PosixArmV7Target.cpp @@ -27,9 +27,9 @@ Result PosixArmV7Target::openCapstone() { } std::unique_ptr PosixArmV7Target::getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) { - return std::make_unique(address, trampoline, handler, content, wrapped, metadata); + return std::make_unique(address, trampoline, handler, content, metadata); } std::unique_ptr PosixArmV7Target::getWrapperGenerator(void* address, WrapperMetadata const& metadata) { diff --git a/src/target/PosixArmV7Target.hpp b/src/target/PosixArmV7Target.hpp index ccddf81..eefcaf7 100644 --- a/src/target/PosixArmV7Target.hpp +++ b/src/target/PosixArmV7Target.hpp @@ -15,7 +15,7 @@ namespace tulip::hook { Result openCapstone() override; std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) override; std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) override; diff --git a/src/target/PosixArmV8Target.cpp b/src/target/PosixArmV8Target.cpp index 2c4a4da..8882205 100644 --- a/src/target/PosixArmV8Target.cpp +++ b/src/target/PosixArmV8Target.cpp @@ -25,9 +25,9 @@ Result PosixArmV8Target::openCapstone() { } std::unique_ptr PosixArmV8Target::getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) { - return std::make_unique(address, trampoline, handler, content, wrapped, metadata); + return std::make_unique(address, trampoline, handler, content, metadata); } std::unique_ptr PosixArmV8Target::getWrapperGenerator(void* address, WrapperMetadata const& metadata) { diff --git a/src/target/PosixArmV8Target.hpp b/src/target/PosixArmV8Target.hpp index e0aabf2..08511b8 100644 --- a/src/target/PosixArmV8Target.hpp +++ b/src/target/PosixArmV8Target.hpp @@ -15,7 +15,7 @@ namespace tulip::hook { Result openCapstone() override; std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) override; std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) override; }; diff --git a/src/target/Target.hpp b/src/target/Target.hpp index 88752c3..d46dbef 100644 --- a/src/target/Target.hpp +++ b/src/target/Target.hpp @@ -44,7 +44,7 @@ namespace tulip::hook { virtual uint32_t getWritableProtection() = 0; virtual std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) = 0; virtual std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) = 0; // sorry :( virtual BaseAssembler* getAssembler(int64_t baseAddress); diff --git a/src/target/Windows32Target.cpp b/src/target/Windows32Target.cpp index 1d7891a..1436c0f 100644 --- a/src/target/Windows32Target.cpp +++ b/src/target/Windows32Target.cpp @@ -75,9 +75,9 @@ Result Windows32Target::openCapstone() { } std::unique_ptr Windows32Target::getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) { - return std::make_unique(address, trampoline, handler, content, wrapped, metadata); + return std::make_unique(address, trampoline, handler, content, metadata); } std::unique_ptr Windows32Target::getWrapperGenerator(void* address, WrapperMetadata const& metadata) { diff --git a/src/target/Windows32Target.hpp b/src/target/Windows32Target.hpp index bde54c2..61ad9e4 100644 --- a/src/target/Windows32Target.hpp +++ b/src/target/Windows32Target.hpp @@ -21,7 +21,7 @@ namespace tulip::hook { uint32_t getWritableProtection() override; std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) override; std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) override; }; diff --git a/src/target/Windows64Target.cpp b/src/target/Windows64Target.cpp index aacc1d3..fd9a9ae 100644 --- a/src/target/Windows64Target.cpp +++ b/src/target/Windows64Target.cpp @@ -24,9 +24,9 @@ Result Windows64Target::openCapstone() { } std::unique_ptr Windows64Target::getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) { - return std::make_unique(address, trampoline, handler, content, wrapped, metadata); + return std::make_unique(address, trampoline, handler, content, metadata); } std::unique_ptr Windows64Target::getWrapperGenerator(void* address, WrapperMetadata const& metadata) { diff --git a/src/target/Windows64Target.hpp b/src/target/Windows64Target.hpp index 16b4a03..3276b7e 100644 --- a/src/target/Windows64Target.hpp +++ b/src/target/Windows64Target.hpp @@ -15,7 +15,7 @@ namespace tulip::hook { Result openCapstone() override; std::unique_ptr getHandlerGenerator( - void* address, void* trampoline, void* handler, void* content, void* wrapped, HandlerMetadata const& metadata + void* address, void* trampoline, void* handler, void* content, HandlerMetadata const& metadata ) override; std::unique_ptr getWrapperGenerator(void* address, WrapperMetadata const& metadata) override; }; diff --git a/test/CallingConventions.cpp b/test/CallingConventions.cpp index 3f8c4a2..9eeb399 100644 --- a/test/CallingConventions.cpp +++ b/test/CallingConventions.cpp @@ -1,7 +1,6 @@ #include #include -#include #include using namespace tulip::hook;