1

Linux x86_64 で sys_call_table のオフセットを取得しようとしています。

まず、system_call エントリへのポインタを MSR_LSTAR から読み取ることで読み取りますが、正しいです

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 ビット ディスプレースメントです。そのため、ptr に 3 を追加し、整数値として逆参照してから ptr に追加します。これは %RIP であり、アドレスは RIP 相対であるためです。しかし、結果の値が間違っています。gdb に表示される値と一致しません。どこが間違っているのでしょうか?

4

1 に答える 1

0

これはx7e9fed00ではなく、-0x7e9fed00-負の変位です。

これは、2の補数の負の数0x81601300の符号の大きさの形式です。

これは、リトルエンディアンプロセッサによって「00136081」として保存されます。


ただし、結果のアドレスにsys_call_tableが見つかるかどうかはわかりません。別のアイデアとして、そこにリストされるべき関数への既知のポインターをメモリーで検索することによってそれを見つける人もいるようです。

于 2012-05-07T15:10:43.200 に答える