如何在Rust中获取给定CPU寄存器的偏移量

时间:2019-03-07 16:35:06

标签: c rust ptrace

作为练习,我一直在尝试使用Rust的nix::sys::ptrace::ptrace(与C的ptrace几乎相同)来通过读取RAX /的内容来仿真strace的系统调用日志记录功能。每次系统调用时,RBX / RCX / 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中!)

1 个答案:

答案 0 :(得分:3)

  

自从我戳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是在addr函数调用中用于ptrace自变量的内容。这就是它的工作方式。请注意,它与其他架构等不同。

PTRACE _ *

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

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

PTRACE_PEEKTEXT-man ptrace(Linux)说-将字数据复制到示踪内存中的地址addr。对于PTRACE_PEEKTEXTPTRACE_PEEKDATA,这两个请求当前是等效的。这是因为Linux没有用于文本和数据的单独地址空间。

Rust和PTRACE_PEEKUSER

nix板条箱提供了getregs函数来读取所有这些文件。它返回libc user_regs_struct。仅Linux支持:

libc的板条箱也包含这些索引:

如果仅对一个寄存器感兴趣,则可以使用此索引来计算ptrace函数的偏移量/ addr。将其与8#[cfg(target_arch = "x86_64")])/ 4#[cfg(target_arch = "x86")])乘以PTRACE_PEEKUSER来读取(请参见Request)。

Rust和PTRACE_PEEKDATA

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

nix板条箱

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

  

从0.10.0开始不推荐使用:ptrace()的使用应改为专用的帮助器功能

您应使用getregsread之类的专用功能。您可以找到其中的列表in the documentation