我正在做一些代码注入,我发现很难把代码从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中使用常量?
3条答案
按热度按时间pgky5nke1#
使用
jmp {}
而不是jmp [{}]
。Rust将操作数放在寄存器中,而不是像C代码那样放在内存中。jmp [{}]
会导致它尝试从寄存器中指定的内存位置读取目标地址。C版本需要方括号,因为目标地址尚未加载到寄存器中。您还需要让编译器知道内联汇编代码使用eax,因此编译器不使用eax作为操作数。要指示eax被乱码,请添加另一个输出操作数
out("eax") _
。_
指示该值可以被丢弃。这有一个缺点,即它使用编译器选择的寄存器,该寄存器可能已经在代码注入的位置使用。
如果编译器默认选择了一个不可用的寄存器,但有另一个寄存器可用,那么可以指定要使用的寄存器。例如,
in("edx") jump_back
会告诉编译器使用edx。8xiog9wr2#
下面是一个只使用eax的可能解决方案:
push
把要跳转到的位置放到堆栈上,并且ret
在加载eax之后跳转到该位置,从而避免了需要单独的寄存器来保存地址。smdncfj33#
这可能是一个暂时的解决方案,但正如帖子中所提到的,它可能会导致未来的问题。
正如prl所注解的,代码段“out(“eax”)_使生成的asm不使用此寄存器。
生成的程序集
突出显示的是可能导致未来问题的因素。