diff --git a/.gitignore b/.gitignore index 58a6dbd..e62caef 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ build balls.asm balls2.asm + +# clangd +.cache/ \ No newline at end of file diff --git a/src/generator/X64Generator.cpp b/src/generator/X64Generator.cpp index bf61494..a7a9640 100644 --- a/src/generator/X64Generator.cpp +++ b/src/generator/X64Generator.cpp @@ -5,6 +5,7 @@ #include "../target/PlatformTarget.hpp" #include +#include using namespace tulip::hook; @@ -758,6 +759,22 @@ Result<> X64HandlerGenerator::relocateBranchInstruction(cs_insn* insn, uint8_t* trampolineAddress += bytes.size(); originalAddress += size; } + else if (targetAddress - reinterpret_cast(m_address) < m_modifiedBytesSize) { + // conditional branch that jmps to code we relocated, so we need to keep track of where it jumps to + // relocation is later done in X86HandlerGenerator::relocatedBytes + std::memcpy(buffer, insn->bytes, size); + if (size == 2) { + auto* relativeByte = reinterpret_cast(buffer + 1); + *relativeByte = -1; + m_shortBranchRelocations[targetAddress] = relativeByte; + } else { + // what + std::cerr << "Unhandled short branch relocation of " << insn->mnemonic << " with size=" << size << std::endl; + } + + trampolineAddress += size; + originalAddress += size; + } else { X64Assembler a(trampolineAddress); RegMem64 m; diff --git a/src/generator/X86Generator.cpp b/src/generator/X86Generator.cpp index b92ff43..e28909b 100644 --- a/src/generator/X86Generator.cpp +++ b/src/generator/X86Generator.cpp @@ -197,6 +197,8 @@ Result X86HandlerGenerator::generateTrampoline(uint64_t target) { Result X86HandlerGenerator::relocatedBytes(uint64_t baseAddress, uint64_t target) { // memcpy(m_trampoline, m_address, 32); + m_modifiedBytesSize = target; + TULIP_HOOK_UNWRAP_INTO(auto cs, Target::get().openCapstone()); cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON); @@ -215,12 +217,22 @@ Result X86HandlerGenerator::relocatedBytes( auto trampolineAddress = baseAddress; std::array buffer; + m_shortBranchRelocations.clear(); while (cs_disasm_iter(cs, &code, &size, &address, insn)) { if (insn->address >= targetAddress) { break; } auto bufferOffset = trampolineAddress - baseAddress; + auto it = m_shortBranchRelocations.find(originalAddress); + if (it != m_shortBranchRelocations.end()) { + auto relByte = it->second; + auto srcOffset = reinterpret_cast(relByte) - buffer.data(); + // why the -1? idk + *relByte = bufferOffset - srcOffset - 1; + m_shortBranchRelocations.erase(it); + } + TULIP_HOOK_UNWRAP(this->relocateInstruction(insn, buffer.data() + bufferOffset, trampolineAddress, originalAddress)); } @@ -259,7 +271,7 @@ Result<> X86HandlerGenerator::relocateInstruction(cs_insn* insn, uint8_t* buffer // branches, jumps, calls if (detail->x86.encoding.imm_offset != 0 && relativeGroup) { intptr_t jmpTargetAddr = static_cast(detail->x86.operands[0].imm) - - static_cast(trampolineAddress) + static_cast(originalAddress); + static_cast(insn->address) + static_cast(originalAddress); return this->relocateBranchInstruction(insn, buffer, trampolineAddress, originalAddress, jmpTargetAddr); } diff --git a/src/generator/X86Generator.hpp b/src/generator/X86Generator.hpp index 1a7a085..58cbca7 100644 --- a/src/generator/X86Generator.hpp +++ b/src/generator/X86Generator.hpp @@ -8,6 +8,10 @@ namespace tulip::hook { class X86HandlerGenerator : public HandlerGenerator { + protected: + uint64_t m_modifiedBytesSize = 0; + // this is only relevant for 64-bit relocation, pointer is to the buffer so dont keep this around + std::unordered_map m_shortBranchRelocations; public: using HandlerGenerator::HandlerGenerator;