ion*_*des 3 64-bit assembly intel
我试图在不使用标签的情况下完全跳过 1 条指令,带有标签的示例是:
cmp r12, r13
je dest ; skip the jmp
jmp whatever
dest:
nop
Run Code Online (Sandbox Code Playgroud)
但是,我的限制是我不能使用标签,所以我假设我必须创建一个相对于 RIP 寄存器的跳转。例如(伪):
cmp r12, r13
je rip+0x05 ; this would obviously depend on the length of the next instruction
jmp whatever
nop
Run Code Online (Sandbox Code Playgroud)
但是,我缺乏生产任何工作的知识,据我所知,没有黑客是不可能读/写 RIP 寄存器的。
编辑:我只熟悉英特尔语法,我使用 Keystone 作为汇编程序。我将从程序集中获取字节并将其加载到可执行内存位置。我正在使用我自己的网站从程序集中获取字节,如果您查看它,您可能会明白。
编辑 2:我尝试了 Jesters 和 Margaret Blooms 的评论,建议使用:
je .+0x05
; or
je $+0x05
Run Code Online (Sandbox Code Playgroud)
但是,我可以确认两者都不适用于 Keystone!幸运的是,我注意到 Keystone 能够处理以下代码:
je +0x05
Run Code Online (Sandbox Code Playgroud)
有没有人能够确认这有效?
编辑 3:我用 NASM 试了一下,$ 前缀在我测试过的代码中工作正常。我用它来测试它:
section .text
global _WinMain@16
_WinMain@16:
jmp $+2+2 ; skip this jmp and the next jmp (each 2 bytes)
jmp $
ret 16
Run Code Online (Sandbox Code Playgroud)
它按预期工作。此外,defuse产生与 Keystone 相同的输出。唯一的区别是 defuse 使用 $ 前缀,而 Keystone 根本不需要!Keystone 等效项是:
jmp +4
jmp .
ret 16
Run Code Online (Sandbox Code Playgroud)
请注意,在 NASM 和 MASM$中不是前缀。 它是一个独立的关键字/符号,指的是当前行的地址。
je $+5行不通:jmp rel32是 5 个字节,而短 JCC 是 2。所以你需要je $+7跳过一个5字节的指令,或者$+4跳过一个2字节的指令。
rel8 位移将是0x05或0x02,因为跳转编码它们从指令末尾开始的位移。但是 NASM 的$标签给出了指令开始的地址,汇编器总是根据目标地址为你计算相对位移。因此,对于$+x,您需要包括当前指令的长度。
如果你想自己编码 rel8,你可以使用db伪指令来发出你想要的字节。例如db 0xEB, 0x02
你不使用任何标签的整个方法/目标从根本上是有缺陷的,除非你有一个可靠的方法来知道下一条指令有多长。(例如,通过使用jmp NEAR或jmp SHORT强制使用长编码或短编码)。你所能做的就是编码一个向前移动固定字节数的跳转,而不是一个跳过一条指令的跳转,无论宽度如何。
但真的只是使用一个标签;无论如何,x86 跳转总是相对的,因此让您的汇编程序使您的生活更轻松并计算正确的相对位移。