如何在 Rust 中获取给定 CPU 寄存器的偏移量
How to get the offset of a given CPU register in Rust
作为练习,我一直在尝试使用 Rust 的 nix::sys::ptrace::ptrace
(这与 C 的 ptrace 几乎相同)通过读取RAX/RBX/RCX/RDX 在每次系统调用时注册。我想要的输出与此类似:
Found syscall: 4
Arg1: 1
Arg2: Hello World!
从我在网上找到的示例来看,PTRACE_PEEKUSER
和 PTRACE_PEEKDATA
的组合似乎最适合实现此目的(也许 PTRACE_GETREGS
也是?),但我我很难理解如何满足我需要传递给这些函数以使其工作的第三个参数。
ptrace
的手册页列出了这个演示正确用法的示例:
ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0);
手册页只是说,"Read a word at the address addr
in the tracee's memory." 但是 addr
应该是什么?我怎样才能确定正确的地址来满足这个论点?
我在网上找到的例子都是这样的:
ptrace(PTRACE_PEEKUSER, pid, sizeof(long)*ORIG_EAX, 0);
或
ptrace(PTRACE_PEEKUSER, pid, somenumber*RAX, 0)
如何find/calculate这些寄存器在运行时的偏移量? (在 Rust 中!)
It's been a long time since I poked Linux kernel (Mac user now). Buf if I remember it correctly then ...
内核headers
安装内核 headers,类似 sudo apt-get install linux-headers-$(uname -r)
。假设您在 x86_64-linux-gnu
(根据您的 rax
兴趣猜测)。
打开/usr/include/x86_64-linux-gnu/sys/reg.h
header:
...
#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
...
评论说:
Index into an array of 8 byte longs returned from ptrace for location of the users' stored general purpose registers.
所有这些宏(RAX
、RCX
、...)为特定寄存器定义了 indexes。因为每个都是 8 字节长(仅 x86_64
),所以偏移量是 8 * $index
。在 rax
寄存器的情况下,偏移量计算为 8 * RAX = 8 * 10 = 80
。 80
是您应该在 ptrace
函数调用中用于 addr
参数的内容。这就是它的工作原理。请注意,它与其他架构等不同。
PTRACE_*
PTRACE_PEEKUSER
- 用于寄存器和其他调试信息。
PTRACE_PEEKDATA
- 用于程序数据和代码。
PTRACE_PEEKTEXT
- man ptrace
(Linux) 表示 - 将字数据复制到被跟踪者内存中的地址addr。至于PTRACE_PEEKTEXT
和PTRACE_PEEKDATA
,这两个请求目前是等价的。那是因为Linux没有单独的文本和数据地址空间。
生锈 & PTRACE_PEEKUSER
nix
箱子提供 getregs function to read all of them. It returns libc
user_regs_struct。仅 Linux 支持:
libc
crate 也包含这些索引:
如果您只对一个寄存器感兴趣,您可以使用此索引来计算 ptrace function. Multiply it with 8
(#[cfg(target_arch = "x86_64")]
) / 4
(#[cfg(target_arch = "x86")]
) and use PTRACE_PEEKUSER
to read it (see Request) 的偏移量/地址。
生锈 & PTRACE_PEEKDATA
阅读 What are the calling conventions for UNIX & Linux system calls on i386 and x86-64. In other words, you're interested in rdi
, rsi
, rdx
, ... registers. The nix
crate provides specialized read function, which internally calls ptrace
函数与 PTRACE_PEEKDATA
。
nix 箱子
ptrace
函数已弃用。文档说明:
Deprecated since 0.10.0: usages of ptrace() should be replaced with the specialized helper functions instead
您应该使用 getregs
和 read
等专用函数。您可以找到它们的列表 in the documentation.
作为练习,我一直在尝试使用 Rust 的 nix::sys::ptrace::ptrace
(这与 C 的 ptrace 几乎相同)通过读取RAX/RBX/RCX/RDX 在每次系统调用时注册。我想要的输出与此类似:
Found syscall: 4
Arg1: 1
Arg2: Hello World!
从我在网上找到的示例来看,PTRACE_PEEKUSER
和 PTRACE_PEEKDATA
的组合似乎最适合实现此目的(也许 PTRACE_GETREGS
也是?),但我我很难理解如何满足我需要传递给这些函数以使其工作的第三个参数。
ptrace
的手册页列出了这个演示正确用法的示例:
ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0);
手册页只是说,"Read a word at the address addr
in the tracee's memory." 但是 addr
应该是什么?我怎样才能确定正确的地址来满足这个论点?
我在网上找到的例子都是这样的:
ptrace(PTRACE_PEEKUSER, pid, sizeof(long)*ORIG_EAX, 0);
或
ptrace(PTRACE_PEEKUSER, pid, somenumber*RAX, 0)
如何find/calculate这些寄存器在运行时的偏移量? (在 Rust 中!)
It's been a long time since I poked Linux kernel (Mac user now). Buf if I remember it correctly then ...
内核headers
安装内核 headers,类似 sudo apt-get install linux-headers-$(uname -r)
。假设您在 x86_64-linux-gnu
(根据您的 rax
兴趣猜测)。
打开/usr/include/x86_64-linux-gnu/sys/reg.h
header:
...
#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
...
评论说:
Index into an array of 8 byte longs returned from ptrace for location of the users' stored general purpose registers.
所有这些宏(RAX
、RCX
、...)为特定寄存器定义了 indexes。因为每个都是 8 字节长(仅 x86_64
),所以偏移量是 8 * $index
。在 rax
寄存器的情况下,偏移量计算为 8 * RAX = 8 * 10 = 80
。 80
是您应该在 ptrace
函数调用中用于 addr
参数的内容。这就是它的工作原理。请注意,它与其他架构等不同。
PTRACE_*
PTRACE_PEEKUSER
- 用于寄存器和其他调试信息。
PTRACE_PEEKDATA
- 用于程序数据和代码。
PTRACE_PEEKTEXT
- man ptrace
(Linux) 表示 - 将字数据复制到被跟踪者内存中的地址addr。至于PTRACE_PEEKTEXT
和PTRACE_PEEKDATA
,这两个请求目前是等价的。那是因为Linux没有单独的文本和数据地址空间。
生锈 & PTRACE_PEEKUSER
nix
箱子提供 getregs function to read all of them. It returns libc
user_regs_struct。仅 Linux 支持:
libc
crate 也包含这些索引:
如果您只对一个寄存器感兴趣,您可以使用此索引来计算 ptrace function. Multiply it with 8
(#[cfg(target_arch = "x86_64")]
) / 4
(#[cfg(target_arch = "x86")]
) and use PTRACE_PEEKUSER
to read it (see Request) 的偏移量/地址。
生锈 & PTRACE_PEEKDATA
阅读 What are the calling conventions for UNIX & Linux system calls on i386 and x86-64. In other words, you're interested in rdi
, rsi
, rdx
, ... registers. The nix
crate provides specialized read function, which internally calls ptrace
函数与 PTRACE_PEEKDATA
。
nix 箱子
ptrace
函数已弃用。文档说明:
Deprecated since 0.10.0: usages of ptrace() should be replaced with the specialized helper functions instead
您应该使用 getregs
和 read
等专用函数。您可以找到它们的列表 in the documentation.