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

大芳姑娘_7652

大芳姑娘_7652

2026-10-27

686人浏览

原创

必须先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):

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 拦截。

Obsidian (Linux)
Obsidian (Linux)

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

下载

解决方法是:用 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) 才行。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++ c++编程 c++安全 linux

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

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

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

2024.03.14

2268

9

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

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

2024.03.14

1039

6

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

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

2024.03.14

447

5

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

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

2024.03.14

327

5

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

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

2024.03.14

426

5

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

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

2024.03.14

600

5

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

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

2024.03.21

1429

9

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

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

2024.03.22

1237

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

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

精品课程

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

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

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

共0课时 | 0人学习