0

我正在尝试做一个可以使用函数 ptrace 检测调用的程序。使用 PTRACE_SINGLESTEP 我可以按指令运行程序指令,然后,当我得到寄存器 RIP 指向的 OP_CODE 0xe8 时,我使用 PTRACE_PEEKTEXT 来获取 RIP 指向的地址之后的 4 个下一个字节。然后,根据我在互联网上找到的文档,这 4 个字节包含一个偏移量,指的是要跳转的位置。似乎 PTRACE_PEEKTEXT 返回了一些奇怪的值,而且我的偏移量太大了。下面是我的代码:

  instr_num = ptrace(PTRACE_PEEKTEXT, this->pid, regs.rip, 0);
  dest = ptrace(PTRACE_PEEKTEXT, this->pid, regs.rip + 1, 0);
  if (instr_num == 0xe8)
    {
      printf("call : %ld\n", regs.rip + dest);
    }

这是输出:

call : -2853719444197214464
call : -2853719444197214464
call : -2853719444197214464

这是 objdump -D 的输出,你可以看到在 main 调用和函数 func 的开头之间有 15 个字节的偏移量:

00000000004004c4 <func>:
4004c4:       55                      push   %rbp
4004c5:       48 89 e5                mov    %rsp,%rbp
4004c8:       5d                      pop    %rbp
4004c9:       c3                      retq   

00000000004004ca <main>:
4004ca:       55                      push   %rbp
4004cb:       48 89 e5                mov    %rsp,%rbp
4004ce:       b8 00 00 00 00          mov    $0x0,%eax
4004d3:       e8 ec ff ff ff          callq  4004c4 <func>
4004d8:       5d                      pop    %rbp
4004d9:       c3                      retq

如果在我检测到一个呼叫之后,我执行一次 ptrace(PTRACE_SINGLESTEP),我的 RIP 会包含我刚刚跳转到的函数的地址吗?根据我的测试,它似乎不是,但我认为它应该。

4

1 回答 1

0

尝试:

printf("call : 0x%lx\n", regs.rip + (long) (int) (dest & (unsigned long) UINT_MAX);

dest是一个 64 位的值,但偏移量在此处编码为 32 位。对于这种代码,以十六进制打印要好得多

于 2013-06-17T19:02:35.587 回答