Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519402
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1172
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-21 13:40
个人简介

技术改变命运

文章分类

全部博文(184)

文章存档

2020年(16)

2017年(12)

2016年(156)

我的朋友

分类: C/C++

2016-07-25 10:21:55

所有的操作系统都提供多种服务的入口点,由此程序向内核请求服务,各种版本的 unix 实
现都提供良好定义,数量有限,直接进入内核的入口点,这些入口点被称为系统调用。内核
的接口被称作系统调用。
实际上 Linux 提供了一种优雅的机制来完成这些:ptrace 系统函数。 ptrace 提供了一种使
父进程得以监视和控制其它进程的方式, 它还能够改变子进程中的寄存器和内核映像, 因而
可以实现断点调试和系统调用的跟踪。
在执行系统调用之前,内核会先检查当前进程是否处于被“跟踪”(traced)的状态。如果是的
话, 内核暂停当前进程并将控制权交给跟踪进程, 使跟踪进程得以察看或者修改被跟踪进程
的寄存器。
在调用 exec 函数之前,子进程用 PTRACE_TRACEME 作为第一个参数调用了 ptrace 函数,它
告诉内核:让别人跟踪我吧!然后,在子进程调用了 execve()之后,它将控制权交还给父
进程。当时父进程正使用 wait()函数来等待来自内核的通知,现在它得到了通知,于是它
可以开始察看子进程都作了些什么,比如看看寄存器的值之类。
long ptrace(enum __ptrace_request request,
pid_t pid,
void *addr,
void *data);
第一个参数决定了 ptrace 的行为与其它参数的使用方法,可取的值有:
出现系统调用之后,内核会将 eax 中的值(此时存的是系统调用号)保存起来,我们可以
使用 PTRACE_PEEKUSER 作为 ptrace 的第一个参数来读到这个值。
我们察看完系统调用的信息后,可以使用 PTRACE_CONT作为 ptrace 的第一个参数,调用
ptrace 使子进程继续系统调用的过程。
通过将 PTRACE_PEEKUSER 作为 ptrace 的第一个参数进行调用, 可以取得与子进程相关的寄
存器值。
在第一部分钟,我们使用 ptrace(PTRACE_TRACEME, …)来跟踪一个子进程,如果你只是
想要看进程是怎么进行系统调用和跟踪程序的, 这个做法是不错的。 但如果你要对运行中的
进程进行调试,则需要使用 ptrace( PTRACE_ATTACH, ….)
当 ptrace( PTRACE_ATTACH, …)在被调用的时候传入了子进程的 pid 时, 它大体是与
ptrace( PTRACE_TRACEME, …)的行为相同的,它会向子进程发送 SIGSTOP 信号,于是
我们可以察看和修改子进程,然后使用 ptrace( PTRACE_DETACH, …)来使子进程继续运
行下去。
形式
#include
int ptrace(int request, int pid, int addr, int data);
描述
Ptrace 提供了一种父进程可以控制子进程运行,并可以检查和改变它的核心
image。它主要用于实现断点调试。一个被跟踪的进程运行中,直到发生一个
信号。则进程被中止,并且通知其父进程。在进程中止的状态下,进程的内存空
间可以被读写。父进程还可以使子进程继续执行,并选择是否是否忽略引起中止
的信号。
Request 参数决定了系统调用的功能:
PTRACE_TRACEME
本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
从内存地址中读取一个字节,内存地址由 addr 给出。
PTRACE_PEEKUSR
从 USER 区域中读取一个字节,偏移量为 addr。
PTRACE_POKETEXT, PTRACE_POKEDATA
往内存地址中写入一个字节。内存地址由 addr 给出。
PTRACE_POKEUSR
往 USER 区域中写入一个字节。偏移量为 addr。
PTRACE_SYSCALL, PTRACE_CONT
重新运行。
PTRACE_KILL
杀掉子进程,使它退出。
PTRACE_SINGLESTEP
设置单步执行标志
PTRACE_ATTACH
跟踪指定 pid 进程。
PTRACE_DETACH
结束跟踪
Intel386 特有:
PTRACE_GETREGS
读取寄存器
PTRACE_SETREGS
设置寄存器
PTRACE_GETFPREGS
读取浮点寄存器
PTRACE_SETFPREGS
设置浮点寄存器
init 进程不可以使用此函数
返回值
成功返回 0。错误返回-1。errno 被设置。
错误
EPERM
特殊进程不可以被跟踪或进程已经被跟踪。
ESRCH
指定的进程不存在
EIO
请求非法
2. 功能详细描述
1) PTRACE_TRACEME
形式:ptrace(PTRACE_TRACEME,0 ,0,0)
描述:本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。
2) PTRACE_PEEKTEXT, PTRACE_PEEKDATA
形式:ptrace(PTRACE_PEEKTEXT, pid, addr, data)
ptrace(PTRACE_PEEKDATA, pid, addr, data)
描述: 从内存地址中读取一个字节, pid 表示被跟踪的子进程, 内存地址由 addr
给出,data 为用户变量地址用于返回读到的数据。在 Linux(i386)中用户
代码段与用户数据段重合所以读取代码段和数据段数据处理是一样的。
3) PTRACE_POKETEXT, PTRACE_POKEDATA
形式:ptrace(PTRACE_POKETEXT, pid, addr, data)
ptrace(PTRACE_POKEDATA,pid, addr, data)
描述: 往内存地址中写入一个字节。 pid 表示被跟踪的子进程, 内存地址由 addr
给出,data 为所要写入的数据。
4) PTRACE_PEEKUSR
形式:ptrace(PTRACE_PEEKUSR, pid, addr, data)
描述:从 USER 区域中读取一个字节,pid 表示被跟踪的子进程,USER 区域
地址由 addr 给出,data 为用户变量地址用于返回读到的数据。USER 结构为
core 文件的前面一部分,它描述了进程中止时的一些状态,如:寄存器值,代
码、数据段大小,代码、数据段开始地址等。在 Linux(i386)中通过
PTRACE_PEEKUSER 和PTRACE_POKEUSR 可以访问 USER 结构的数
据有寄存器和调试寄存器。
5) PTRACE_POKEUSR
形式:ptrace(PTRACE_POKEUSR, pid, addr, data)
描述:往 USER 区域中写入一个字节,pid 表示被跟踪的子进程,USER 区域
地址由 addr 给出,data 为需写入的数据。
6) PTRACE_CONT
形式:ptrace(PTRACE_CONT, pid, 0, signal)
描述:继续执行。pid 表示被跟踪的子进程,signal 为 0 则忽略引起调试进程
中止的信号,若不为 0 则继续处理信号 signal。
7) PTRACE_SYSCALL
形式:ptrace(PTRACE_SYS, pid, 0, signal)
描述:继续执行。pid 表示被跟踪的子进程,signal 为 0 则忽略引起调试进程
中止的信号,若不为 0 则继续处理信号 signal。与 PTRACE_CONT 不同的
是进行系统调用跟踪。在被跟踪进程继续运行直到调用系统调用开始或结束时,
被跟踪进程被中止,并通知父进程。
8) PTRACE_KILL
形式:ptrace(PTRACE_KILL,pid)
描述:杀掉子进程,使它退出。pid 表示被跟踪的子进程。
9) PTRACE_SINGLESTEP
形式:ptrace(PTRACE_KILL, pid, 0, signle)
描述: 设置单步执行标志, 单步执行一条指令。 pid 表示被跟踪的子进程。 signal
为 0 则忽略引起调试进程中止的信号,若不为 0 则继续处理信号 signal。当被
跟踪进程单步执行完一个指令后,被跟踪进程被中止,并通知父进程。
10) PTRACE_ATTACH
形式:ptrace(PTRACE_ATTACH,pid)
描述:跟踪指定 pid 进程。pid 表示被跟踪进程。被跟踪进程将成为当前进程
的子进程,并进入中止状态。
11) PTRACE_DETACH
形式:ptrace(PTRACE_DETACH,pid)
描述:结束跟踪。pid 表示被跟踪的子进程。结束跟踪后被跟踪进程将继续执
行。
12) PTRACE_GETREGS
形式:ptrace(PTRACE_GETREGS, pid, 0, data)
描述:读取寄存器值,pid 表示被跟踪的子进程,data 为用户变量地址用于返
回读到的数据。此功能将读取所有 17 个基本寄存器的值。
13) PTRACE_SETREGS
形式:ptrace(PTRACE_SETREGS, pid, 0, data)
描述:设置寄存器值,pid 表示被跟踪的子进程,data 为用户数据地址。此功
能将设置所有 17 个基本寄存器的值。
14) PTRACE_GETFPREGS
形式:ptrace(PTRACE_GETFPREGS, pid, 0, data)
描述:读取浮点寄存器值,pid 表示被跟踪的子进程,data 为用户变量地址用
于返回读到的数据。此功能将读取所有浮点协处理器 387 的所有寄存器的值。
15) PTRACE_SETFPREGS
形式:ptrace(PTRACE_SETREGS, pid, 0, data)
描述:设置浮点寄存器值,pid 表示被跟踪的子进程,data 为用户数据地址。
此功能将设置所有浮点协处理器 387 的所有寄存器的值。


阅读(1716) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~