JMP到绝对地址(操作码)
-
20-09-2019 - |
题
我想编写一个EXE打包机/保护作为学习更多关于汇编,C ++的方式,以及如何PE文件的工作。我现在懂了工作,所以含有EP部分进行异或用钥匙和一个新的部分是创建一个包含我的解密代码。一切顺利伟大除非我解密后尝试JMP到原来的EP。
基本上我这样做:
DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
crypted.put(0xE9);
crypted.write((char*)&orginalEntryPoint, sizeof(DWORD));
但是,而不是它跳转到入口点,OllyDbg的表明该代码拆卸为:
00404030 .-E9 00100000 JMP 00405035 ; should be 00401000 =[
和当我尝试在奥利手动更改它的新的操作码显示为
00404030 -E9 CBCFFFFF JMP crypted.00401000
在哪里0xCBCFFFFF从何而来?如何将产生从C ++侧?
解决方案
我认为E9
为相对跳转操作码:其操作数指定的相对距离要跳转,加上或从下一个指令开始减
如果你想操作数指定一个绝对地址,就需要有不同的操作码。
其他提示
您可以使用:
mov eax,DESTINATION_VA
jmp eax ; pick any register the destination doesn't care about
或
push DESTINATION_VA
ret ; not recommended for performance
这和下一个先进的16 ret
指示要回调用树比这更高的深度将错误预测,除非他们被更深的调用深度推离返回地址预测栈。 (当前的CPU通常具有16入口预测器堆)。
相对E9
jmp
编码用于这样的:
CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])
推+ RET是最小的解决方案,如果你有VA地址和图像不重新定位,但它仍然是6个字节,以便它比直接jmp rel32
大。
寄存器间接可能是最有效的,如果你不能用正常的直接jmp
。
操作码为绝对间接跳转是FF + 4字节地址。这是最经常用于存储在数据地址的jumptables。
绝对地址做需要重定位时不加载到预期的地址,所以相对地址通常是优选的。代码相对跳跃也是2个字节以下。
英特尔优化手册表明CPU预计呼叫和RET以成对使用,因此没有呼叫RET在回答2建议将导致他们所谓的“性能损失”。
此外,如果代码没有被加载到编译器假定相同的地址,所述RET可能会程序崩溃。这将是更安全的,以计算的相对地址。
不隶属于 StackOverflow