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++方面生成这个?

我认为 E9< /Cl>是相对跳跃的操作码:它的操作数指定了一个相对的跳跃距离,从下一个指令开始的正或负。
如果希望操作数指定绝对地址,则需要不同的操作码。

我认为
E9
是相对跳转的操作码:它的操作数指定要跳转的相对距离,从下一条指令开始的正负距离

如果希望操作数指定绝对地址,则需要不同的操作码。

可以使用:

push DESTINATION_VA
ret

相对E9 jmp编码的使用方式如下:

CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])
如果您有VA地址且图像未重新定位,则push+ret是最佳解决方案

您可以使用:

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可能会使程序崩溃。计算相对地址会更安全。

绝对间接跳转的操作码是FF+4字节地址。这通常用于数据中存储的地址跳转表

绝对地址在未加载到预期地址时需要重新定位,因此通常首选相对地址。相对跳转的代码也要小2个字节

Intel optimization manual声明cpu期望call和ret成对使用,因此回答2中建议的没有调用的ret将导致所谓的“性能损失”


此外,如果代码没有加载到编译器假定的相同地址,ret可能会使程序崩溃。计算相对地址会更安全。

关于E9的替代品有什么想法吗?跳转通常是相对的。有一个用于跳转到绝对远地址的操作码
EA
,还有一个用于跳转到间接地址的操作码(操作数指定包含要跳转到的地址的内存位置)。这并没有回答问题,只是确认OP的答案是错误的。@baordog问题是,“0xCBCFFFFF从何而来?”无论如何,OP显然理解答案,并且/或者对评论中的
EA
感到满意。关于E9的替代品有什么想法吗?跳转通常是相对的。跳转到绝对远地址有一个操作码
EA
,跳转到间接地址有一个操作码(其中操作数指定包含要跳转到的地址的内存位置)。这并没有回答问题,只是确认OP的答案是错误的。@baordog问题是,“0xCBCFFFFF从何而来?”?"无论如何,OP显然理解了答案,并且/或者对评论中的
EA
感到满意。也许你的意思是FF 25 4byte..FF 4 byte毫无意义。@Laie它仍然有意义,因为
FF
是操作码,我们知道助记符是
jmp
。它可能是
FF/4
或者
FF/5
,因为它们都是绝对间接跳跃——一个是近距离跳跃,另一个是远距离跳跃。但是是的,
FF 25 aa bb cc dd
是你观察的方式
FF/4
(两者中比较常见的一种)在机器代码中。最后一段不正确:
push imm32
/
ret
不会崩溃,重新定位代码不会更改
ret
跳转到的绝对目标地址。问题是性能:返回地址堆栈不平衡将导致某些未来的返回预测失误。A
mov reg,imm32
+2字节register间接跳转可能是最好的选择(而不是从内存加载指针)如果出于某种原因,你不能从一个已知地址编码一个
jmp rel32
,…最好也提到一个64位模式的匹配jmp操作码。也许你的意思是FF 25 4byte..FF 4 byte毫无意义。@Laie它仍然有意义,因为
FF
是操作码,我们知道助记符是
jmp
。它可以e
FF/4
FF/5
因为它们都是绝对间接跳跃——一个是近距离跳跃,另一个是远距离跳跃。但是是的,
FF 25 aa bb cc dd
是你观察
FF/4
的方式(两者中比较常见的一种)在机器代码中。最后一段不正确:
push imm32
/
ret
不会崩溃,重新定位代码不会更改
ret
跳转到的绝对目标地址。问题是性能:返回地址堆栈不平衡将导致某些未来的返回预测失误。A
mov reg,imm32
+2字节regi如果出于某种原因您不能只编码
jmprel32
f,那么sterindirectjump可能是您最好的选择(而不是从内存加载指针)