简体   繁体   中英

Linux sys_call_table rip relative addressing x86_64

I am trying to get offset of sys_call_table on Linux x86_64.

First of all I read pointer to system_call entry by reading it from MSR_LSTAR and it's correct

static unsigned long read_msr(unsigned int msr)
{

    unsigned low, high;
    asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
    return ((low) | ((u64)(high) << 32));
}

Then I parse it to find opcode of call instruction and it is also correct

#define CALL_OP 0xFF
#define CALL_MODRM 0x14
static unsigned long find_syscall_table(unsigned char *ptr)
{

  //correct
  for (; (*ptr != CALL_OP) || (*(ptr+1) != CALL_MODRM); ptr++);

  //not correct
  ptr += *(unsigned int*)(ptr + 3);
  pr_info("%lx", (unsigned long)ptr);


  return ptr;
}

But I failed to get address after call opcode. First byte of ptr is opcode, then ModRM byte, then SIB and then 32bit displacement, so I add 3 to ptr and dereferenced it as integer value and then add it to ptr, because it is %RIP, and address is RIP relative. But the result value is wrong, it don't coincide with value I see in gdb, so where am I wrong?

It's not x7e9fed00 but rather -0x7e9fed00 - a negative displacement.

That is the sign-magnitude form of the 2's complement negative number 0x81601300

which is stored by a little-endian processor as "00 13 60 81"


No idea if you will find sys_call_table at the resulting address however. As an alternative idea, it seems some people find it by searching memory for the known pointers to functions that should be listed in it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM