【问题标题】:How to interpret PTRACE_PEEKTEXT return value如何解释 PTRACE_PEEKTEXT 返回值
【发布时间】:2017-04-14 13:15:22
【问题描述】:

为了熟悉寄存器,我一直在重新编写一个不使用 PTRACE_SYSCALL 的小型 strace 程序。

所以在我的代码中使用 ptrace(PTRACE_GETREGS, ...) 设置 user_reg_struct 字段后,我使用 ptrace(PTRACE_PEEKDATA, ...) 从中读取。

我真的不知道如何处理该函数的返回以使用它的数据(系统调用等...),我开始查看一些代码并遇到了类似的事情:

int is_a_syscall() {

struct user_reg_struct regs;
unsigned short int ret;

ret = ptrace(PTRACE_PEEKDATA, pid, regs.rip, 0);
if (ret == 0xFFFF) {
   perror("failed")
   exit(1); }
if (ret == 0x80CD || ret == 0x50F)
   return (true);
return (false);
}

现在有人可以向我解释 if() 语句中的数字是什么,也就是:

  • 0xFFFF,我认为这与处理器的架构有关,但我无法验证
  • 0x80CD0x50F

我想知道它们是什么,在哪里可以找到它们,我可以解释它们以及如何使用它们来获取我的系统调用和它们的参数。

【问题讨论】:

    标签: c unix system-calls strace


    【解决方案1】:

    您包含的代码有些不合常规,所以我将解释它的作用,然后展示一种不同的方法。

    unsigned short int ret;
    ret = ptrace(PTRACE_PEEKDATA, pid, regs.rip, 0);
    

    Linux 上的 ptrace 返回一个 long,而不是 unsigned short。代码的作者只是在看 ptrace 返回的 4 或 8 个字节的低位 2 个字节。由于 x86 是 little-endian,因此可以完成工作,但稍后我将展示另一种方法。

    if (ret == 0xFFFF) {
       perror("failed")
       exit(1); }
    

    ptrace 在失败时返回 -1。由于代码只存储了返回值的低位 2 字节,并且将该值视为无符号,因此 -1 的测试使用 0xFFFF 代替。

    由于ptrace(PTRACE_PEEKDATA, ...)即使成功也可以返回-1,所以最好也看看errno(我稍后会展示)。

    if (ret == 0x80CD || ret == 0x50F)
       return (true);
    return (false);
    

    您可以在 http://ref.x86asm.net/coder64.html 等网站找到操作码列表。 CDintCD80int 800F05syscall。这是 x86 Linux 中用于执行系统调用的两个操作码。更多信息请访问What is better “int 0x80” or “syscall”?

    这是检查系统调用指令的另一种方法(未经测试):

    int is_a_syscall(regs)
    struct user_reg_struct regs;
    {
        long ret;
        unsigned char primary, secondary;
        extern int errno;
    
        errno = 0;
        ret = ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
        if (ret == -1 && errno != 0) {
            perror("failed")
            exit(1);
        }
        primary = (unsigned)0xFF & ret;
        secondary = ((unsigned)0xFF00 & ret) >> 8;
        if (primary == 0xCD && secondary == 0x80 || primary == 0x0F && secondary == 0x05)
            return true;
        return false;
    }
    

    我使用 ptrace 的返回值的全宽。如果它是 -1 并且如果 errno 已设置,则表示错误。我也使用PTRACE_PEEKTEXT 而不是PTRACE_PEEKDATA,尽管在x86 上没关系。位掩码用于获取主要和次要操作码字节。

    如何使用它们来获取我的系统调用及其参数。

    对此,请看这个详细回答:What are the calling conventions for UNIX & Linux system calls on x86-64

    【讨论】:

      【解决方案2】:

      您的意思是这些与十进制有何关系(例如 0x80CD = 32973),或者它们与 ptrace() 相关的语义是什么(例如 0xFFFF 可能意味着函数遇到错误)?

      如果是前者,这些是以十六进制表示的数字。即数字范围由以下组成的数字系统:0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。

      如果是后者,请查看man page for ptrace中的返回值部分

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-14
        • 1970-01-01
        • 2012-11-06
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多