【问题标题】:How to get the offset of a given CPU register in Rust如何在 Rust 中获取给定 CPU 寄存器的偏移量
【发布时间】:2019-03-07 16:35:06
【问题描述】:

作为练习,我一直在尝试使用 Rust 的 nix::sys::ptrace::ptrace(与 C 的 ptrace 几乎相同)通过读取 RAX/RBX/RCX/ 的内容来模拟 strace 的系统调用日志记录功能。 RDX 在每次系统调用时注册。我想要的输出类似于:

Found syscall: 4
Arg1: 1
Arg2: Hello World!

从我在网上找到的示例看来,PTRACE_PEEKUSERPTRACE_PEEKDATA 的组合最适合完成此任务(也许 PTRACE_GETREGS 也是?),但我很难理解如何以满足我需要传递给这些函数以使其工作的第三个参数。

ptrace 的手册页列出了这个示例,展示了正确的用法:

ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0);

手册页只是说:“在被跟踪者的内存中读取地址addr 的单词。”但是addr 应该是什么?如何确定满足这个论点的正确地址?

我在网上找到的例子都有这样的:

ptrace(PTRACE_PEEKUSER, pid, sizeof(long)*ORIG_EAX, 0);

ptrace(PTRACE_PEEKUSER, pid, somenumber*RAX, 0)

如何在运行时查找/计算这些寄存器的偏移量? (在 Rust 中!)

【问题讨论】:

    标签: c rust ptrace


    【解决方案1】:

    自从我戳Linux内核(现在是Mac用户)以来已经很长时间了。如果我没记错的话……

    内核头文件

    sudo apt-get install linux-headers-$(uname -r) 之类的东西安装内核头文件。假设您在x86_64-linux-gnu 上(根据您对rax 的兴趣猜测)。

    打开/usr/include/x86_64-linux-gnu/sys/reg.h 标头:

    ...
    #ifdef __x86_64__
    /* Index into an array of 8 byte longs returned from ptrace for
       location of the users' stored general purpose registers.  */
    
    # define R15    0
    # define R14    1
    # define R13    2
    # define R12    3
    # define RBP    4
    # define RBX    5
    # define R11    6
    # define R10    7
    # define R9     8
    # define R8     9
    # define RAX    10
    ...
    

    评论说:

    索引到从 ptrace 返回的 8 字节长的数组中,用于定位用户存储的通用寄存器。

    所有这些宏(RAXRCX、...)为特定的寄存器定义了索引。因为每个都是 8 字节长(仅限x86_64),所以偏移量是8 * $index。对于rax 寄存器,偏移量计算为8 * RAX = 8 * 10 = 8080 是您应该在 ptrace 函数调用中使用 addr 参数。这就是它的工作原理。请注意,它对于其他架构等有所不同。

    PTRACE_*

    PTRACE_PEEKUSER - 用于寄存器和其他调试信息。

    PTRACE_PEEKDATA - 用于程序数据和代码。

    PTRACE_PEEKTEXT - man ptrace (Linux) 说 - 将字数据复制到被跟踪者内存中的地址 addr。至于PTRACE_PEEKTEXTPTRACE_PEEKDATA,这两个请求目前是等价的。那是因为Linux没有单独的文本和数据地址空间。

    Rust 和 PTRACE_PEEKUSER

    nix crate 提供getregs 函数来读取所有这些。它返回libcuser_regs_struct。仅 Linux 支持:

    libc crate 也包含这些索引:

    如果您只对一个寄存器感兴趣,您可以使用该索引来计算ptrace 函数的偏移量/地址。将它与8 (#[cfg(target_arch = "x86_64")]) / 4 (#[cfg(target_arch = "x86")]) 相乘,然后使用PTRACE_PEEKUSER 读取它(参见Request)。

    锈 & PTRACE_PEEKDATA

    阅读What are the calling conventions for UNIX & Linux system calls on i386 and x86-64。换句话说,您对rdirsirdx、...寄存器感兴趣。 nix crate 提供专门的read 函数,其中internally calls ptrace 函数与PTRACE_PEEKDATA

    nix 板条箱

    ptrace 函数已弃用。文档说明:

    自 0.10.0 起已弃用:应将 ptrace() 的用法替换为专门的辅助函数

    您应该使用专门的函数,例如 getregsread。你可以找到他们的名单in the documentation

    【讨论】:

      猜你喜欢
      • 2018-04-03
      • 1970-01-01
      • 2017-03-05
      • 2016-11-11
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      • 2019-11-09
      相关资源
      最近更新 更多