11#include " Hook.hpp"
22
33#include < Zydis/Zydis.h>
4+ #include < cstring>
5+ #include < vector>
6+ #include < expected>
7+ #include < string>
8+ #include < cstdint>
49
5- // 修复原始指令中的RIP相对寻址
6- // raw_code: 原始机器码
7- // old_base: 原始代码地址(hookTarget)
8- // new_base: 调度器中的新地址(pAsmDispatcher + 已生成代码大小)
910std::expected<std::vector<uint8_t >, std::string> MulNX::Memory::HookEx::FixRIPRelativeInstructions (
1011 const std::vector<uint8_t >& raw_code,
1112 uintptr_t old_base,
@@ -24,54 +25,79 @@ std::expected<std::vector<uint8_t>, std::string> MulNX::Memory::HookEx::FixRIPRe
2425 &instr, operands);
2526
2627 if (!ZYAN_SUCCESS (status)) {
27- // 解码失败,直接复制剩余字节(理论上不应发生,但做保护)
28+ // 解码失败,直接复制剩余字节
2829 fixed.insert (fixed.end (), raw_code.begin () + offset, raw_code.end ());
2930 break ;
3031 }
3132
3233 uintptr_t old_instr_addr = old_base + offset;
3334 uintptr_t new_instr_addr = new_base + fixed.size ();
3435
35- // 提取当前指令原始字节(将用于修改)
36+ // 提取当前指令原始字节
3637 std::vector<uint8_t > instr_bytes (
3738 raw_code.begin () + offset,
3839 raw_code.begin () + offset + instr.length );
3940
40- // 遍历操作数,查找RIP相对寻址
41- for (size_t i = 0 ; i < instr.operand_count ; ++i) {
42- const auto & op = operands[i];
43- if (op.type == ZYDIS_OPERAND_TYPE_MEMORY &&
44- op.mem .base == ZYDIS_REGISTER_RIP ) {
45- // 获取原始位移(注意可能是负值)
46- // Zydis stores displacement info in `disp.size`/`disp.value` (no `has_displacement` flag)
47- int64_t orig_disp = (op.mem .disp .size != 0 ) ? op.mem .disp .value : 0 ;
48-
49- // 原始目标地址 = 旧指令地址 + 指令长度 + 原始位移
50- uint64_t target = old_instr_addr + instr.length + orig_disp;
51-
52- // 新位移 = 目标 - (新指令地址 + 指令长度)
53- int64_t new_disp = target - (new_instr_addr + instr.length );
54-
55- // 检查32位范围(RIP相对寻址使用有符号32位)
56- if (new_disp < -2147483648LL || new_disp > 2147483647LL ) {
57- // 超出范围,需要更复杂的处理(比如蹦床),此处可记录错误或断言
58- // 暂时仍赋值,但可能导致崩溃
59- return std::unexpected (" 无法成功!" );
41+ bool handled = false ;
42+
43+ // ---------- 1. 处理相对转移指令 (jmp/call/jcc rel32) ----------
44+ if (instr.meta .branch_type == ZYDIS_BRANCH_TYPE_NEAR &&
45+ (instr.attributes & ZYDIS_ATTRIB_IS_RELATIVE )) {
46+ for (size_t i = 0 ; i < instr.operand_count ; ++i) {
47+ const auto & op = operands[i];
48+ if (op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE && op.imm .is_relative ) {
49+ // 获取该立即数在指令中的偏移和大小(字节)
50+ // 注意:instr.raw.imm[i] 与操作数索引 i 对应
51+ size_t imm_offset = instr.raw .imm [i].offset ;
52+ size_t imm_size = instr.raw .imm [i].size / 8 ; // 通常为4 (rel32)
53+
54+ // 读取原始32位相对偏移(有符号)
55+ int32_t orig_disp = 0 ;
56+ memcpy (&orig_disp, raw_code.data () + offset + imm_offset, imm_size);
57+
58+ // 原始目标地址 = 当前指令地址 + 指令长度 + 原始偏移
59+ uint64_t target = old_instr_addr + instr.length + orig_disp;
60+
61+ // 新偏移 = 目标 - (新指令地址 + 指令长度)
62+ int64_t new_disp = static_cast <int64_t >(target) - (new_instr_addr + instr.length );
63+
64+ if (new_disp < INT32_MIN || new_disp > INT32_MAX ) {
65+ return std::unexpected (" 相对跳转偏移超出32位范围,无法修复" );
66+ }
67+
68+ int32_t new_disp32 = static_cast <int32_t >(new_disp);
69+ memcpy (instr_bytes.data () + imm_offset, &new_disp32, imm_size);
70+ handled = true ;
71+ break ;
6072 }
73+ }
74+ }
75+
76+ // ---------- 2. 处理 RIP 相对寻址 ----------
77+ if (!handled) {
78+ for (size_t i = 0 ; i < instr.operand_count ; ++i) {
79+ const auto & op = operands[i];
80+ if (op.type == ZYDIS_OPERAND_TYPE_MEMORY &&
81+ op.mem .base == ZYDIS_REGISTER_RIP ) {
82+ int64_t orig_disp = (op.mem .disp .size != 0 ) ? op.mem .disp .value : 0 ;
83+ uint64_t target = old_instr_addr + instr.length + orig_disp;
84+ int64_t new_disp = target - (new_instr_addr + instr.length );
85+
86+ if (new_disp < INT32_MIN || new_disp > INT32_MAX ) {
87+ return std::unexpected (" RIP相对偏移超出32位范围,无法修复" );
88+ }
6189
62- // 定位指令中的位移字段并修改
63- // `instr.raw.disp.size` is zero when no displacement bytes are present
64- if ( instr.raw .disp .size != 0 ) {
65- size_t disp_offset = instr. raw . disp . offset ; // 字节偏移
66- size_t disp_size = instr. raw . disp . size / 8 ; // 字节数(通常为4)
67- int32_t disp_to_write = static_cast < int32_t >(new_disp);
68- memcpy (instr_bytes. data () + disp_offset, &disp_to_write, disp_size) ;
90+ if (instr. raw . disp . size != 0 ) {
91+ size_t disp_offset = instr. raw . disp . offset ;
92+ size_t disp_size = instr.raw .disp .size / 8 ;
93+ int32_t disp_to_write = static_cast < int32_t >(new_disp);
94+ memcpy (instr_bytes. data () + disp_offset, &disp_to_write, disp_size);
95+ }
96+ break ;
6997 }
70- break ; // 一条指令一般只有一个RIP相对操作数
7198 }
7299 }
73100
74- // 将修复后的指令加入结果
75101 fixed.insert (fixed.end (), instr_bytes.begin (), instr_bytes.end ());
76102 offset += instr.length ;
77103 }
0 commit comments