目录

linux-ptrace-图文详解一基础介绍

linux ptrace 图文详解(一)基础介绍


(代码: 6.3.1,架构:arm64)

One look is worth a thousand words.  —— Tess Flanders

引言

在现代操作系统中,对于开发者来说,能够深入理解和控制进程的行为是解决复杂问题的关键。Linux提供了多种机制来实现这一目标,而 ptrace 系统调用无疑是其中最为强大和灵活的工具之一。尽管 ptrace 的功能强大,它的使用和实现原理却相对复杂,需要对操作系统内核机制有深入的理解。许多开发者在使用 ptrace 时,往往只停留在表面,而对于其底层实现知之甚少。

为了帮助开发者更好理解和应用ptrace,笔者将推出一系列文章,深入探讨 ptrace 的各个功能及其详细实现原理。本系列文章将从基础概念入手,逐步深入到每个功能的具体实现,包括: 进程控制、寄存器操作、内存读写、系统调用跟踪、断点设置、单步调试等 。

在本系列的第一篇文章中,笔者将对 ptrace 进行基本介绍,包括其定义、功能、应用场景等。通过这篇文章,读者将对 ptrace 有一个全面的了解,为后续深入学习ptrace实现原理打下坚实的基础。

让我们一起踏上探索 ptrace 的旅程,解锁其强大功能。

一、ptrace 基础介绍

ptrace 是 linux内核 提供的一个系统调用,并非一个标准的posix接口,ptrace 主要用于进程跟踪和调试。它运行一个用户态进程(通常称为跟踪器, Tracer)控制和监视另一个进程(称为被调试进程, Tracee)的执行。ptrace是许多调试跟踪工具(如:GDB、strace 等)的 “基座”,其函数原型如下:

https://i-blog.csdnimg.cn/direct/824c3e1f9b604569ba5f323a0c955ac5.png

参数:

request: 用于标识一个需要执行的操作;

pid: 标识目标线程ID

addr、data: 一个内存地址和附加信息,其语义因选择的操作而不同;

这里详细介绍下ptrace系统调用中的参数request,通过该参数,ptrace为用户态提供了丰富的进程调试跟踪功能。

1)PTRACE_TRACEME

允许当前进程被其父进程跟踪,通常用于GDB加载运行一个被调试程序;

2)PTRACE_PEEKTEXT

读取目标进程的代码段内容,通常用于GDB查看目标进程的指令代码;

3)PTRACE_PEEKDATA

读取目标进程的数据段内容,通常用于

GDB查看目标进程的全局变量、堆栈内容等 ;

4)PTRACE_PEEKUSER

读取目标进程的用户态寄存器和状态信息,通常用于GDB查看目标进程的PC、SP等;

5)PTRACE_POKETEXT

修改目标进程的代码段内容,用于GDB修改目标进程的指令代码,例如

设置 软断点

6)PTRACE_POKEDATA

修改目标进程的数据段内容,用于

GDB修改目标进程的全局变量、堆栈内容等数据 ;

7)PTRACE_POKEUSER

修改目标进程的用户态寄存器和状态信息;

8)PTRACE_CONT

唤醒目标进程继续执行,通常用于

GDB的continue功能 ;

9)PTRACE_KILL

终止目标进程,用于GDB杀死被调试进程;

10)PTRACE_SINGLESTEP

单步执行目标进程,通常用于

GDB的 step单步调试 目标进程的功能 ;

11)PTRACE_GETREGS

获取目标进程的寄存器状态,如当前的程序计数器(PC)、栈指针(SP)等;

12)PTRACE_SETREGS

设置目标进程的寄存器状态;

13)PTRACE_ATTACH

用于attach到一个正在运行的目标进程,通常用于

GDB attach调试功能 ;

14)PTRACE_DETACH

从一个目标进程上detach,通常用于GDB解除对目标进程的调试功能;

15)PTRACE_SYSCALL

在目标进程的系统调用入口处、返回处暂停,通常

用于strace工具捕获目标进程的系统调用 ;

16)PTRACE_SETOPTIONS

设置目标进程的跟踪选项,通常用于

GDB设置是否对目标进程的一些操作(如:fork、pthread_create、exec、所有系统调用等)进行跟踪 ;

17)PTRACE_GETSIGINFO

获取目标进程的信号信息,通常用于

GDB获取目标进程的异常地址、exit_code、pending信号 等信息;

18)PTRACE_GETEVENTMSG

获取目标进程与特定 ptrace事件 相关联的消息,例如

GDB获取目标进程fork创建的子进程/子线程pid信息 、位于系统调用入口处/出口处 等信息;

19)PTRACE_GETREGSET

获取目标进程的寄存器集合;

20)PTRACE_SETREGSET

设置目标进程的寄存器集合,通常用于

GDB设置目标进程的 硬断点、观察点

二、ptrace 常见应用场景

1、gdb进程调试

gdb对目标进程进行跟踪调试,其底下依赖的主要是linux内核中的 ptrace功能、以及 signal + wait 这两个用于同步的系统调用。通过ptrace接口,gdb可以对被调试进程进行一系列的调试跟踪操作。

2、strace 系统调用跟踪

strace是一个用户态的工具,其主要用途是跟踪目标进程执行期间的所有系统调用操作,获取对应系统调用的参数、返回值等信息。strace底层依赖的就是ptrace(PTRACE_SYSCALL)这一功能,做到对目标进程的所有系统调用操作进行监控。

3、动态注入

通过ptrace系统调用,可以用于向目标进程注入代码或数据,在某些情况下用于功能扩展或漏洞利用。

三、gdb 与 ptrace

这里简单介绍下GDB调试,GDB调试主要分为以下两种方法:

1)本地调试

该方式下,调试程序(GDB) 和 被调试程序(Tracee)运行在同一台电脑中。可以使用 “gdb加载运行被调试程序” 或 “gdb attach到正在运行的被调试程序” 这两个模式进行调试。

https://i-blog.csdnimg.cn/direct/517f31c501c34838a6b7386f925ef1a0.png

2)远程调试

GDB远程调试的方式,主要用于嵌入式的场景,由于GDB这个程序本身体积比较大,在某些容量比较下的嵌入式目标机中,没有充足的资源用于运行庞大的GDB。因此,GDB也提供远程调试的方式:gdb server程序 运行在目标机上,gdb client运行在调试机上。由于gdb server程序的体积比较小,所以可以在大部分嵌入式目标机上运行,gdb client运行在调试机上,通过网络/串口与目标机上运行的gdb server进行通知,并通过gdb server调试控制目标程序。

https://i-blog.csdnimg.cn/direct/20dd06dea0af44c88c6d1cc0f6f6b710.png

以下总结了gdb中常用的一些操作,以及其底层对应的ptrace操作。本系列后续文章将围绕以下功能进行深入探讨。

https://i-blog.csdnimg.cn/direct/7486982d509d4fa5814a8cf2a3b30068.png