讲师中心 微信公众号
AI工具推荐 视频效率加速

C++ Linux下怎么使用ptrace系统调用跟踪和修改另一个进程的内存

大芳姑娘_7652

大芳姑娘_7652

发布时间:2026-10-27 13:17:47

|

686人浏览过

|

来源于php中文网

原创

必须先attach并waitpid等待目标进程进入stopped状态,否则后续ptrace操作会失败;attach后需处理SIGSTOP、对齐内存访问、修改代码段前需mprotect改权限,并在detach前恢复寄存器和信号状态。

c++ linux下怎么使用ptrace系统调用跟踪和修改另一个进程的内存

ptrace 跟踪目标进程前必须先 attach 并处理 SIGSTOP

Linux 下 ptrace 不能直接“热插拔”进一个正在运行的进程;必须让目标进程处于可被控制的状态。常见错误是调用 ptrace(PTRACE_ATTACH, pid, nullptr, nullptr) 后立刻读内存,结果失败或返回 -1 —— 因为内核此时已向目标进程发送 SIGSTOP,但你还没等它真正停止就去操作了。

正确做法是:waitpid(pid, &status, 0) 阻塞等待目标进入 stopped 状态(WIFSTOPPED(status) == true)。否则后续所有 ptrace(PTRACE_PEEKDATA) 或 PTRACE_POKEDATA 都会返回 -1 并设 errno = ESRCH(进程不存在或不可访问)或 EIO(I/O 错误,实际多因未停稳)。

  • 目标进程若本身忽略 SIGSTOP(极少见),attach 会失败,errno = EPERM
  • 普通用户只能 trace 自己启动的子进程,或拥有 CAP_SYS_PTRACE 能力(如 root)才能 attach 其他用户进程
  • ptrace 是单次生效的:每次 peek/poke 后,目标仍保持 stopped 状态,直到你显式 ptrace(PTRACE_CONT, ...)

用 PTRACE_PEEKDATA / PTRACE_POKEDATA 读写内存要对齐且注意字节序

ptrace 的内存操作接口只支持按 long(即寄存器宽度)读写:在 x86_64 上是 8 字节,在 i386 上是 4 字节。直接传入一个 char* 地址去改单个字节?不行 —— 你得先 PEEKDATA 拿到整个 word,修改对应字节,再 POKEDATA 写回去。

示例:想把地址 0x7fffe1234567 处的第 3 个字节(从 0 开始)改成 0x99(x86_64):

立即学习“C++免费学习笔记(深入)”;

Obsidian (Linux)
Obsidian (Linux)

操作 Obsidian 库(纯 Markdown 笔记),并通过 notesmd-cli 实现自动化。

下载
long word = ptrace(PTRACE_PEEKDATA, pid, (void*)0x7fffe1234560, nullptr);
// 假设地址 0x7fffe1234567 落在该 word 的 offset=7 位置(因为 0x67 - 0x60 = 7)
unsigned char* p = (unsigned char*)&word;
p[7] = 0x99;
ptrace(PTRACE_POKEDATA, pid, (void*)0x7fffe1234560, (void*)word);
  • 地址必须按 sizeof(long) 对齐,否则 ptrace 返回 -1,errno = EIO
  • 不要依赖目标进程的 endianness —— ptrace 总是按宿主机字节序读写,而用户空间内存布局就是宿主机序,所以无需额外转换
  • 写入后不会自动刷 cache,但现代 x86/x86_64 的 store buffer 不会导致可见性问题;不过若目标进程正执行该地址附近指令,可能触发 SEGV_MMAP 或执行旧指令缓存(需 __builtin___clear_cache() 或 sys_icache_invalidate,但 glibc 不暴露,通常靠 mprotect(..., PROT_READ|PROT_WRITE|PROT_EXEC) 触发刷新)

修改代码段前必须先 mprotect 改写权限,否则 PTRACE_POKEDATA 失败

即使你成功 attach 并停稳了进程,尝试往 .text 段(比如函数入口)写数据时,ptrace(PTRACE_POKEDATA, ...) 仍大概率返回 -1,errno = EIO。这不是 ptrace 的限制,而是底层页表标记为只读(PROT_READ|PROT_EXEC),写操作被 MMU 拦截。

解决方法是:用 ptrace(PTRACE_GETREGS, ...) 拿到目标进程的 user_regs_struct,从中提取 rip 或查 /proc/pid/maps 确定目标地址所属 vma,再调用 ptrace(PTRACE_SYSCALL, ...) 让目标自己执行一次 mprotect 系统调用(需构造栈/寄存器上下文),或者——更简单但需 root —— 在 tracer 进程中用 process_vm_writev(绕过 ptrace)配合 mprotect 注入(但这就偏离 ptrace 主线了)。

  • 普通用户无法让目标进程执行任意系统调用,除非它原本就在 syscall 中断点上(比如刚 execve 完)
  • 更可行的做法是:仅修改堆或栈上的数据(如全局变量、局部变量地址),这些区域默认可写;若真要 patch 代码,优先考虑 LD_PRELOAD 或 gdb --pid 交互式 patch
  • ptrace 修改内存后,目标恢复执行前,务必确认 CPU 指令缓存已同步(尤其 ARM64 需显式 ic ivau,但用户态无权限;此时建议避免 patch 正在执行的代码页)

detach 前忘记恢复寄存器或信号状态会导致目标崩溃

很多人 ptrace(PTRACE_ATTACH) → PEEKDATA → POKEDATA → PTRACE_DETACH 就完事,结果目标进程 segfault 或卡死。根本原因是:DETACH 不会自动恢复被修改过的寄存器(比如你动过 rip 或 rax),也不会重置挂起的信号(如 attach 时收到的 SIGSTOP 可能还在 pending 状态)。

安全 detach 流程必须包含:

  • 调用 ptrace(PTRACE_GETREGS, pid, nullptr, &regs) 保存原始寄存器(最好在 attach 后立即做)
  • 如有修改,用 PTRACE_SETREGS 恢复 rip、rsp 等关键寄存器
  • 用 ptrace(PTRACE_SETOPTIONS, pid, nullptr, PTRACE_O_TRACEEXIT) 等选项控制退出行为,或手动 kill(pid, SIGCONT) 清除 pending 的 SIGSTOP
  • 最后才 ptrace(PTRACE_DETACH, pid, nullptr, nullptr) —— 此时内核会自动向目标发 SIGCONT,但前提是它没有其他阻塞信号

最隐蔽的坑:目标进程若在 read() 等可中断 sleep 中被 attach,waitpid 返回后它的 task_struct->state 是 TASK_INTERRUPTIBLE,但 DETACH 不保证唤醒它;必须显式 kill(pid, SIGCONT) 才行。

热门AI工具

更多
超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2268

2024.03.14

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

1039

2024.03.14

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

447

2024.03.14

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

327

2024.03.14

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

426

2024.03.14

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

600

2024.03.14

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

1429

2024.03.21

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

1237

2024.03.22

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

100

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn