我想编写一个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可能会程序崩溃。这将是更安全的,以计算的相对地址。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top