Chr*_*ini 6 x86 assembly executable masm opcode
我正在尝试编写一个exe包装器/保护器作为一种学习更多关于汇编程序,c ++以及PE文件如何工作的方法.我现在已经开始工作,所以包含EP的部分与一个密钥进行异或,并创建一个包含我的解密代码的新部分.一切都很好,除非我在解密后尝试JMP到原始EP.
基本上我这样做:
DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
crypted.put(0xE9);
crypted.write((char*)&orginalEntryPoint, sizeof(DWORD));
Run Code Online (Sandbox Code Playgroud)
但是,它不是跳到入口点,而是显示此代码反汇编为:
00404030 .-E9 00100000 JMP 00405035 ; should be 00401000 =[
Run Code Online (Sandbox Code Playgroud)
当我尝试手动更改它时,新的操作码显示为
00404030 -E9 CBCFFFFF JMP crypted.00401000
Run Code Online (Sandbox Code Playgroud)
0xCBCFFFFF来自哪里?我如何从C++端生成它?
Bar*_*cik 17
你可以使用:
push DESTINATION_VA
ret
Run Code Online (Sandbox Code Playgroud)
要么
mov eax,DESTINATION_VA
jmp eax
Run Code Online (Sandbox Code Playgroud)
这个和下一个最多16个__CODE__
指令返回调用树高于这个深度将错误预测,除非它们被更深的调用深度推离返回地址预测器堆栈.(当前CPU通常具有16个条目的预测器堆栈).
相对__CODE__
__CODE__
编码使用如下:
CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])
Run Code Online (Sandbox Code Playgroud)
push + ret是最小的解决方案,如果你有VA地址并且图像没有重新定位,但它仍然是6个字节,所以它比直接大__CODE__
.
如果你不能使用普通直接,那么注册间接可能是最有效的__CODE__
.
我认为这E9
是一个相对跳转的操作码:它的操作数指定要跳过的相对距离,加上或减去下一条指令的开头.
如果希望操作数指定绝对地址,则需要不同的操作码.
小智 5
绝对间接跳转的操作码是FF + 4byte地址。这最常用于存储在数据中的地址的跳转表。
绝对地址在未加载到预期地址时确实需要重定位,因此通常首选相对地址。相对跳转的代码也小2个字节。
英特尔优化手册指出,CPU预期呼叫和重新使用将成对使用,因此答案2中建议的没有呼叫的重新使用会导致他们所谓的“性能下降”。
另外,如果代码未加载到编译器假定的相同地址,则ret可能会使程序崩溃。计算相对地址会更安全。