如何在字节码中表示和使用 JMP /5

逆向工程 部件 操作系统 x64 字节码
2021-07-01 21:34:43

我在 OSX 平台上使用 x86_64。我已经研究出如何使用 E9 字节代码指令进行近跳转,其中我的相对地址有 4 个字节(与 RIP 合作)
现在我有一个实例,我在一个非常高的地址和我所在的位置分配了一些东西将在同一过程中引用它非常遥远。最终结果是 RIP 和起始地址之间的差异为 5 个字节。(如果我使用相对寻址)。我试图使用 FF 25 + 4 个字节 + 1 个字节,第五个没有被解释为命令的一部分。
确实当我在表中查找数据时x86 架构 mod R/M 字节它指出 FF 25(显然是 RIP+signed dword)。这将解释为什么 1 个字节被丢弃。我试着检查表格,但并没有真正理解它。

所以我的问题是

  1. 我如何阅读表格以了解如何设置字节码,以便我可以正确地做问题#3?
  2. JMP /5 使用直接地址还是间接地址(我是否必须将 RIP 作为计算的一部分)?
  3. 我需要组装哪些字节码才能使 JMP /5 生效(例如:FF ...)

典型的 4 字节跳转 (e9) 代码可能如下所示:(lldb session)

-> 0x100000ebb:  81 7d fc 03 00 00 00  cmpl   $0x3, -0x4(%rbp)
   0x100000ec2:  0f 85 05 00 00 00     jne    0x100000ecd           
   0x100000ec8:  e9 3b 57 34 12        jmp    0x112346608
   0x100000ecd:  48 8d 3d bc 00 00 00  leaq   0xbc(%rip), %rdi  
2个回答

AMD64 中没有 JMP-64bit-OFFSET 指令(不要问我,通常他们对新操作码并不吝啬)。

来自x86asm.net 的关于 JMPF 的引用

AMD64 架构程序员手册第 3 卷:如果操作数大小为 32 或 64 位,则操作数为 16 位选择器,后跟 32 位偏移量。(在 AMD64 架构上,不支持 64 位偏移)

相反,人们会做的是使用这样的间接跳转:

mov rax, 0x100000ebb
jmp rax

这也适用于 32 位应用程序并直接跳转到寄存器中包含的地址(无偏移)。

有关更多信息,请查看 StackOverflow 上的相关问题:此处此处

编辑:

关于汇编器和符号:字节序列中的最高值位通常被认为是符号位。例如,当使用相对跳转时,它会将偏移量视为两个补码。如果结果为负,则从指令指针中减去该数字。

这可能与您的场景无关,如果是这样,我深表歉意。:) 我在试图弄清楚为什么相对跳跃似乎偏离了 5 个字节时看到了你的帖子。所以我想把这个答案留在这里,以防其他人在同一条路上跌跌撞撞。

TL;DR:x86 相对跳转使用偏移量,其位移是相对于下一条指令的。

我正在查看一些程序集并试图找出 +5 字节的来源......

0x7FFE9BAD116D : E9 74690000 ; jmp to 0x7FFE9BAD7AE6

我正在计算 0x7FFE9BAD116D + 6974(记住我们在小端)= 7FFE9BAD7AE1 ,所以我对 5 个字节的差异感到困惑。

我查了一下 E9 操作码,看到了答案:

跳近、相对、相对于下一条指令的位移。

所以在我上面的例子中,当前指令是 5 字节(1 字节操作码加 4 字节地址偏移)。