news 2026/8/23 15:19:13

intentrace底层实现(上):ptrace是如何拦截Linux进程每一次系统调用的

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
intentrace底层实现(上):ptrace是如何拦截Linux进程每一次系统调用的

intentrace底层实现(上):ptrace是如何拦截Linux进程每一次系统调用的

【免费下载链接】intentraceintentrace is strace with intent, it goes all the way for you instead of half the way. intentrace is currently in beta项目地址: https://gitcode.com/gh_mirrors/in/intentrace

intentrace 是一个"带意图"的 strace 替代工具:它基于 Linux 的 ptrace 机制拦截并记录进程中每一次系统调用,再通过推理启发式告诉你每次调用"到底想干什么"。本文带你深入 intentrace 的底层实现(上篇),搞懂 ptrace 是如何拦截 Linux 进程的系统调用的。

运行效果:一眼看懂系统调用追踪 🖥️

先看看它追踪google-chrome启动过程时的输出——每一行都是一次被 ptrace 拦截的系统调用,右侧=>之后是 intentrace 对结果的"意图化"解读:

传统 strace 只会打印read(3, 0x7ffd..., 4096) = 832这样的原始信息,你还需要自己查手册理解每个参数的含义。而 intentrace 会直接解释为"从文件描述符 3 读取 832 字节"、"映射内存失败:权限被修改"等自然语言结论。

双进程架构:fork + PTRACE_TRACEME 埋下伏笔

intentrace 追踪一个新程序时,并没有直接运行它,而是在 main.rs 中采用经典的fork 双进程结构(参考parent()child_trace_me()函数):

  1. 父进程:调用fork()创建子进程,自己进入主循环负责"拦截";
  2. 子进程:先调用ptrace::traceme()(即PTRACE_TRACEME)声明"我被追踪",然后exec目标程序。

PTRACE_TRACEME的作用是让子进程此后每次进入/退出系统调用时都会自动停下来,并把控制权交还父进程。这是 ptrace 拦截体系的第一块基石。

💡 如果目标是已经在运行的进程,intentrace 则用-p <pid>配合ptrace::attach动态附加,原理完全相同。

ptrace 的核心机制:一次系统调用 = 两次停顿 🔍

父进程的主循环(src/main.rsparent()函数)围绕一个简单动作展开:反复执行

ptrace::syscall(pid) → 等待子进程停下来 → 读取寄存器 → 放行

PTRACE_SYSCALL让被追踪进程在每次系统调用入口和出口各停顿一次,于是父进程拿到两帧"快照":

停顿时机关键寄存器拿到什么
入口(entering)orig_rax系统调用号(如openatmmap
入口rdi rsi rdx r10 r8 r9最多 6 个调用参数
出口(exiting)rax返回值或错误码

为什么必须读orig_rax而不是rax?因为系统调用返回时rax会被返回值覆盖,而orig_rax是内核原样保留的"原始调用号",是区分进入还是返回的唯一可靠依据。

代码中用一个syscall_entering布尔量在两次停顿之间切换状态:入口时构造SyscallObject并解析参数,出口时读取rax判定成败,再PTRACE_SYSCALL放行进程,直到进程退出(ESRCH)结束整个循环。

偷看别人内存:peek & poke 阶段 👀

光有寄存器里的参数还不够——比如openat的参数只是一个指向路径字符串的指针。要解读出真实路径,必须读取被追踪进程的内存。

intentrace 把这一步封装在 peeker_poker.rs(名字致敬 ptrace 文档里"读写被追踪进程内存"的术语 peek/poke),核心是process_vm_readv系统调用:

  • read_bytes:按定长读取远程内存;
  • read_bytes_variable_length:读取变长数据(如 C 字符串),并小心处理跨 4KiB 页边界的半读问题;
  • read_bytes_as_struct:把读到的字节块直接转成内存结构体。

这样,像截图中readlink /usr/bin/google-chrome => /etc/alternatives/google-chrome这类"解析出符号链接真实目标"的能力,就是靠远程读内存实现的。

从原始参数到"意图":SyscallObject 与骨架映射 ⚙️

拦截到一次调用后,intentrace 还需要回答两个问题:参数是什么类型?返回值该怎么解读?

  • 骨架映射(syscall_skeleton_map.rs):为每个系统调用登记一份"形状"描述,例如read的返回是字节数或Errnommap的返回是地址或MAP_FAILED。目前覆盖了 380+ 个 Linux 系统调用中最常用的约 166 个,遵循"少数调用覆盖绝大多数软件"的策略(类似 UniKraft 内核的思路);
  • 调用对象(syscall_object.rs):SyscallObject把调用号、被追踪 PID、进入/退出状态和结果聚合在一起,fill_buffer()负责渲染成终端上那行带颜色的人话输出;
  • 返回值解析src/return_resolvers.rssrc/utilities.rs):把rax解释为"成功 + N 字节"或"失败 + errno 含义",比如EPERM会被翻译成具体的权限说明。

这就是 intentrace 与 strace 的本质区别:拦截靠 ptrace,理解靠推理——它不止展示"发生了什么",还解释"这意味着什么"。

快速上手:构建并运行 intentrace 🚀

git clone https://gitcode.com/gh_mirrors/in/intentrace cd intentrace cargo build --release

几个常用命令:

intentrace -q ls # -q 屏蔽被追踪程序自身的输出 intentrace -f docker run alpine # -f 追踪 fork 出的子进程 intentrace -Z ls # -Z 只看失败的系统调用 intentrace -C ls # -C 额外打印统计汇总表

注意:当前 beta 版本仅支持 x86-64 架构,多线程程序支持仍在完善中。

小结

intentrace 的拦截链路可以浓缩为一句话:子进程PTRACE_TRACEME自曝 → 父进程PTRACE_SYSCALL双停顿 →getregsorig_rax和参数寄存器 →process_vm_readv偷读内存还原指针内容 → 骨架映射 + 返回值解析输出"意图"。下一篇我们将深入参数解析与"意图推理"的启发式细节。

【免费下载链接】intentraceintentrace is strace with intent, it goes all the way for you instead of half the way. intentrace is currently in beta项目地址: https://gitcode.com/gh_mirrors/in/intentrace

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 15:17:31

十分钟搞定游戏 DLSS 版本替换:DLSS Swapper 实操手册

十分钟搞定游戏 DLSS 版本替换&#xff1a;DLSS Swapper 实操手册 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 还原一个真实的 DLSS 版本滞后场景 刚把显卡升级完&#xff0c;我们进游戏打开光追&#xff0c;画面依…

作者头像 李华
网站建设 2026/8/23 15:15:13

为什么你需要Lanarky:构建LLM微服务的终极Python Web框架全解析

为什么你需要Lanarky&#xff1a;构建LLM微服务的终极Python Web框架全解析 【免费下载链接】lanarky The web framework for building LLM microservices [deprecated] 项目地址: https://gitcode.com/gh_mirrors/la/lanarky Lanarky 是一个专为构建 LLM 微服务 而生的…

作者头像 李华
网站建设 2026/8/23 15:13:59

ide-eval-resetter如何帮你一键重置JetBrains IDE的30天试用期

ide-eval-resetter如何帮你一键重置JetBrains IDE的30天试用期 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter IDE 弹出"试用期已结束"&#xff0c;重构变灰、提示全停&#xff0c;代码写到一半被掐断。…

作者头像 李华