assembly 内嵌asm jmp - '指令的操作数无效'

rsaldnfx  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(224)

我正在做一些代码注入,我发现很难把代码从C转换成Rust。
情况如下,在相对地址0x 40147 D处,我们将跳转到dll注入的指令的地址,这是通过手动插入字节来完成的。

let rel = target_address - to_hook - 5;

let bytes: [u8; 4] =  transmute(rel.to_be());

buf[0] = 0xE9;

for x in 1..5 {
    buf[x] = bytes[4-x]
}

因此,我们在asm中运行任何代码,在结束时,它都应返回到0x 401484,即指令0x 40147 D + 7。在C中,这按预期工作,而在Rust中则不然。
丙:

DWORD jmp_back = 0x40147D + 7;

__asm {
    add dword ptr[ebp - 0x0C], 03
    mov eax, [ebp - 0x0C]
    jmp [jmp_back]
}

Rust(我贴了一个标签,以免程序崩溃):

let jump_back: u32 = 0x40147D + 7;

unsafe {
    asm!(
        "2:",
        "add dword ptr [ebp-0x0C],01",
        "mov eax,[ebp-0x0C]",
        // "jmp 2b", //back to label 2
        "jmp [{}]", in(reg) jump_back,

        // 'invalid operand for instruction' 
        //"jmp 0x401484" 

    );
 }

什么是被忽视的?

编辑

正如@prl所注解的,删除方括号会导致:

我正在研究eax寄存器里面到底是什么。但是这个修改导致程序崩溃并关闭。

OBS为了进行测试,我删除了以前的jmp指令(“jmp 5D 7 B145 D”)
编辑2

Inline Asm所述,显然是为了在指令中使用值作为操作数,Rust在块的开始处将值加载到寄存器中。
所以可能是我的指令也使用相同的寄存器的问题。
我稍后再试,但我可能必须更改Rust使用的寄存器。

理想的做法是不必为这样的操作使用寄存器。

编辑3

到目前为止我留下我的答案作为这个问题的解决方案,但它仍然有问题。
rust 作asm块的第一条指令把你想用的值移到寄存器中,几点说明:

  • 如果寄存器中包含值?
  • 为什么不在块asm中使用常量?
pgky5nke

pgky5nke1#

使用jmp {}而不是jmp [{}]。Rust将操作数放在寄存器中,而不是像C代码那样放在内存中。jmp [{}]会导致它尝试从寄存器中指定的内存位置读取目标地址。C版本需要方括号,因为目标地址尚未加载到寄存器中。
您还需要让编译器知道内联汇编代码使用eax,因此编译器不使用eax作为操作数。要指示eax被乱码,请添加另一个输出操作数out("eax") __指示该值可以被丢弃。

asm!(
    "add dword ptr [ebp-0x0C],01",
    "mov eax,[ebp-0x0C]",
    "jmp {}", in(reg) jump_back, out("eax") _
);

这有一个缺点,即它使用编译器选择的寄存器,该寄存器可能已经在代码注入的位置使用。
如果编译器默认选择了一个不可用的寄存器,但有另一个寄存器可用,那么可以指定要使用的寄存器。例如,in("edx") jump_back会告诉编译器使用edx。

8xiog9wr

8xiog9wr2#

下面是一个只使用eax的可能解决方案:

asm!(
    "push eax",
    "add dword ptr [ebp-0x0C],01",
    "mov eax,[ebp-0x0C]",
    "ret", in("eax") jump_back,
);

push把要跳转到的位置放到堆栈上,并且ret在加载eax之后跳转到该位置,从而避免了需要单独的寄存器来保存地址。

smdncfj3

smdncfj33#

这可能是一个暂时的解决方案,但正如帖子中所提到的,它可能会导致未来的问题。
正如prl所注解的,代码段“out(“eax”)_使生成的asm不使用此寄存器。

unsafe {
    asm!(
        "add dword ptr [ebp-0x0C],01",
        "mov eax,[ebp-0x0C]",
        "jmp {}", in(reg) 0x401484u32,
        out("eax") _
     );
}

生成的程序集

突出显示的是可能导致未来问题的因素。

相关问题