我正在尝试在 Linux x86_64 上获取 sys_call_table 的偏移量。
首先,我通过从 MSR_LSTAR 读取指向 system_call 条目的指针,它是正确的
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));
}
然后我解析它找到调用指令的操作码,它也是正确的
#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;
}
但是我在调用操作码后无法获取地址。 ptr 的第一个字节是操作码,然后是 ModRM 字节,然后是 SIB,然后是 32 位位移,所以我将 3 添加到 ptr 并将其解引用为整数值,然后将其添加到 ptr,因为它是 %RIP,地址是 RIP 相对的。但是结果值是错误的,它与我在 gdb 中看到的值不一致,所以我哪里错了?
最佳答案
它不是 x7e9fed00 而是 -0x7e9fed00 - 负位移。
也就是2的补负数0x81601300的符号量级形式
由小端处理器存储为“00 13 60 81”
不知道您是否会在结果地址找到 sys_call_table。作为另一种想法,似乎有些人是通过在内存中搜索指向应该列在其中的函数的已知指针来找到它的。
关于Linux sys_call_table rip 相对寻址 x86_64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10468533/