组合远距离呼叫或远距离跳跃(j *指令) [英] Assemble far calls or far jumps (j* instructions)
问题描述
我正在尝试创建一个分配表,该表更改某些指令在AllocateMemoryOnRemoteProcess
分配的另一个地址中的位置.
I'm trying to create a dispatch table which changes the location of some instruction in another address which is allocated by AllocateMemoryOnRemoteProcess
.
我遇到的问题之一是几乎所有的Calls
和所有的Jumps
都是near
和relative
,只要我将程序集加载到新位置,那么这些指令就不会工作.
One of the problems that I encountered was almost all of Calls
and all kind of Jumps
are near
and relative
and as long as I load the assemblies in new location, then these instructions won't work.
据我所知,我应该将这些指令转换为far jump
或far call
,在谷歌搜索过程中看到的一种解决方案是使用push
和ret
,如:
As I know I should convert these instructions to far jump
or far call
one of the solutions that I saw during my googling was using push
and ret
like :
push 0xdeadbeef
ret
或者有人建议使用寄存器进行绝对寻址,如:
or someone suggests using registers for absolute addressing like :
mov %eax,0xdeadbeef
jmp %eax
这些解决方案在我的情况下不起作用,因为只要我处于函数例程中,更改堆栈状态或在第二种情况下,更改类似%eax
的寄存器都会导致失败.
These solutions won't work in my case because as long as I'm in a function routine, changing the stack state or in the second case changing a register like %eax
causes failure.
此问题中的某人写道:
Someone in this question wrote :
- 调用远(使用操作码9A)跳转到绝对段和偏移. 即,就像立即设置CS和?IP.
- call far (with opcode 9A) jumps to an absolute segment and offset. ie, it's like setting CS and ?IP at once.
所以看来我应该对far calls
使用带9A
的操作码,但这仅适用于调用,而且我不知道要使用这种方法转换各种跳转!
So it seems I should use opcode with 9A
for far calls
, but this just works for the calls and I have no idea about converting all kinds of Jumps with this method!
我经常使用objdump
来反汇编二进制文件,然后使用以下命令将clang
用作汇编器:
I regularly use objdump
to disassemble a binary, then use clang
as the assembler by using the following command :
clang -c MyAsm.asm -m32
但是当我使用上述命令进行汇编时,结果是相对的.
But when I assemble with the above command then the result is relative.
例如,当MyAsm.asm
为时:
call 0x402af2
objdump
的结果是:
MyAsm.o: file format Mach-O 32-bit i386
Disassembly of section __TEXT,__text:
__text:
0: e8 ed 2a 40 00 calll 4205293 <__text+0x402AF2>
这些结果是相对的.
所以我的问题是:
- 如何用
clang
或任何其他工具(当然,它们同时适用于80x86和Amd64结构)来组装far calls
或far jumps
(j*
指令)? - 是否还有其他使用相对寻址的指令(如调用或跳转),所以我应该重新组装以避免出现此问题?
- How can I assemble
far calls
orfar jumps
(j*
instructions) withclang
or any other tools (which of course, work for both 80x86 and Amd64 structures)? - Is there any other instruction like calls or jumps that use relative addressing, so I should reassemble in order to avoid the problem?
推荐答案
如果您可以保留一个寄存器,建议您使用
If you can spare a register, I advise you to use
movabs $addr,%rax
jmp *%rax
,或者,如果您可以确保地址在地址空间的前2 GB之内,
or, if you can ensure that the address is within the first 2 GB of address space,
mov $addr,%eax
jmp *%eax
强烈建议您不要使用
push $addr
ret
因为这破坏了返回预测,使接下来的几个函数返回速度比必需的慢.跳远和呼叫(ljmp
和lcall
)是红色鲱鱼.尽管可以在技术上使用它们,但它们并不能帮助您实现目标,并且实际上是为了不同的目的(更改cs
),并且在现代处理器上以慢速,微编码的指令实现.
as this trashes the return prediction, making the next few function returns slower than necessary. Far jumps and calls (ljmp
and lcall
) are a red herring. While they could technically be used, they won't help you achieve your goal and are actually meant for a different purpose (changing cs
) and are implemented as slow, micro-coded instructions on modern processors.
如果您不能保留寄存器,则可以使用以下技巧:
If you cannot spare a register, you can use this sort of trick instead:
jmp *0f(%rip)
0: .quad addr
这应该可以正常工作,并且不需要您使用额外的寄存器.但是,它比使用寄存器要慢.
This should just work and in addition doesn't require you to use an extra register. It is slower than using a register though.
请注意,条件跳转严格要求跳转目标必须是立即执行的.如果要有条件地跳转到绝对地址,请使用如下习惯用法:
Note that conditional jumps strictly require the jump target to be immediate. If you want to do a conditional jump to an absolute address, use an idiom like this:
# for jz addr
jnz 1f
jmp *0f(%rip)
0: .quad addr
1:
这篇关于组合远距离呼叫或远距离跳跃(j *指令)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!