问题
I'm trying to create a dispatch table which changes the location of some instruction in another address which is allocated by AllocateMemoryOnRemoteProcess
.
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.
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
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 :
- call far (with opcode 9A) jumps to an absolute segment and offset. ie, it's like setting CS and ?IP at once.
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!
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.
For example when MyAsm.asm
is :
call 0x402af2
The result of objdump
is :
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>
These results are relative.
So my questions are :
- 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?
回答1:
If you can spare a register, I advise you to use
movabs $addr,%rax
jmp *%rax
or, if you can ensure that the address is within the first 2 GB of address space,
mov $addr,%eax
jmp *%eax
I strongly advise you against using
push $addr
ret
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:
来源:https://stackoverflow.com/questions/48498308/assemble-far-calls-or-far-jumps-j-instructions