Assembly JMP到绝对地址(操作码) 我试图编写一个EXE打包器/保护器,作为学习汇编程序、C++和PE文件工作的一种方式。我现在已经让它工作了,所以包含EP的部分用一个密钥XORD,并创建了一个包含我的解密代码的新部分。除了解密后我尝试和JMP到原始EP之外,一切都很顺利
基本上我是这样做的:Assembly JMP到绝对地址(操作码) 我试图编写一个EXE打包器/保护器,作为学习汇编程序、C++和PE文件工作的一种方式。我现在已经让它工作了,所以包含EP的部分用一个密钥XORD,并创建了一个包含我的解密代码的新部分。除了解密后我尝试和JMP到原始EP之外,一切都很顺利,assembly,x86,executable,masm,opcode,Assembly,X86,Executable,Masm,Opcode,基本上我是这样做的: DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint; // -- snip -- // crypted.put(0xE9); crypted.write((char*)&orginalEntryPoint, sizeof(DWORD)); 但是,ollydbg并没有跳转到入口点,而是将此代码反汇编为: 00404030 .-E9 00100000 JMP 0040
DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
crypted.put(0xE9);
crypted.write((char*)&orginalEntryPoint, sizeof(DWORD));
但是,ollydbg并没有跳转到入口点,而是将此代码反汇编为:
00404030 .-E9 00100000 JMP 00405035 ; should be 00401000 =[
当我试图在olly中手动更改它时,新的操作码显示为
00404030 -E9 CBCFFFFF JMP crypted.00401000
0xCBCFFFFF来自哪里?我如何从C++方面生成这个? 我认为
push DESTINATION_VA
ret
或
相对E9 jmp编码的使用方式如下:
CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])
如果您有VA地址且图像未重新定位,则push+ret是最佳解决方案绝对间接跳转的操作码为FF+4字节地址。这通常用于数据中存储的地址跳转表 绝对地址在未加载到预期地址时需要重新定位,因此通常首选相对地址。相对跳转的代码也要小2个字节 Intel optimization manual声明cpu期望call和ret成对使用,因此回答2中建议的没有调用的ret将导致所谓的“性能损失”
此外,如果代码没有加载到编译器假定的相同地址,ret可能会使程序崩溃。计算相对地址会更安全。关于E9的替代品有什么想法吗?跳转通常是相对的。有一个用于跳转到绝对远地址的操作码
EA
,还有一个用于跳转到间接地址的操作码(操作数指定包含要跳转到的地址的内存位置)。这并没有回答问题,只是确认OP的答案是错误的。@baordog问题是,“0xCBCFFFFF来自哪里?“无论如何,OP显然理解答案,并且/或者对评论中的EA
感到满意。也许你的意思是FF 25 4字节.”。。FF 4字节毫无意义。@Laie它仍然有意义,因为FF
是操作码,我们知道助记符是jmp
。它可以是FF/4
或FF/5
,因为它们都是绝对间接跳,一个是近跳,另一个是远跳。但是,是的,FF 25 aa bb cc dd
是您在机器代码中观察到的FF/4
(两者中较常见的一种)。最后一段不正确:push imm32
/ret
不会崩溃,重新定位代码不会更改ret
跳转到的绝对目标地址。问题在于性能:不平衡返回地址堆栈将导致某些未来的返回预测失误。如果出于某种原因,您不能仅从已知地址对jmp rel32
进行编码,那么mov reg,imm32
+2字节寄存器间接跳转可能是您最好的选择(而不是从内存加载指针)。如果能为64位模式提供一个匹配的jmp操作码,那就太好了。我正在为64位地址空间寻找一个类似的方法,带有操作码。@ThomasTempelmann:covers x86-64。用push
/ret
解决了严重的性能问题,但不幸的是海报将其回滚。如果您关心现代x86上的性能,请使用mov-eax,dst
/jmp-eax
,而不是使用与调用不匹配的ret
()来平衡返回地址预测器。和/或见mov
/jmp
与推送相比额外花费1个字节,避免了未来的分支预测失误。如果您从目标客户那里获得了ret
,那么在RE.SE有一个类似的问题,我提供了一个非常详细的解释:
CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])