Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help understanding FF indirect call instruction x86

I'm trying to recode a simple ftrace but I'm having trouble understanding FF indirect calls like this one :

ff 15 76 0b 20 00       callq  *0x200b76(%rip)        # 600ff0 <__libc_start_main@GLIBC_2.2.5>

Does it work like the E8 instruction with an offset ? If not, how to find the address the call point to ? And the address of return of that call ?

like image 540
Theo Champion Avatar asked Mar 10 '23 04:03

Theo Champion


2 Answers

The instruction callq *0x200b76(%rip) does the following things:

  1. Load one 64 bit word from rip + 0x200b76 where rip is the instruction pointer. According to the comment, this should be the address 0x600ff0 but it can be different if your code is relocated.
  2. Push the address of the next instruction on the stack as a return address.
  3. Jump to the value of the datum we read in step one.

The difference to the normal call (i.e. opcode e8) instruction is that this is an indirect function call where the address we call is loaded from memory instead of being specified right there. This is indicated by the asterisk (*). call foo is to call *foo like mov $foo,%eax is to mov foo,%eax.

like image 65
fuz Avatar answered Mar 23 '23 05:03

fuz


Jumps can be characterized by several properties:

  • Direct or indirect (i.e. whether the address is given in the instruction or retrieved from a memory pointer).

  • Relative (address is given as an increment, relative to where the CALL opcode is) or absolute (jump to the actual, provided address). Indirect jumps are always absolute.

  • Near (in the same segment) or far (in a different segment). Far jumps are always absolute.

Now, E8 is direct, near, and relative. In contrast, FF is indirect, near, and absolute. There is a variant of FF that's far rather than near, which is used mainly for call gates AFAIK. See here for a succinct table of CALLs.

See also this: How can I tell if jump is absolute or relative?.

So to your questions:

how to find the address the call point to

The 15 indicates that the pointer is relative to RIP (if it were relative e.g. to RAX then you'd have ff 90). The offset relative to RIP is in the four bytes immediately following the 15 - in your example, these are 0x00200b76. See Why call instruction opcode is represented as FF15? for additional explanation on decoding.

the address of return of that call

The return address is always the instruction immediately following the CALL instruction. So if the CALL is at address 0x100000 then the return address will be 0x100006.

like image 30
YSK Avatar answered Mar 23 '23 03:03

YSK