使用ptrace统计指令数【没有什么用的程序】
最近在学习动态分析的时候注意到了ptrace
这个系统调用
这个系统调用的功能很强大,它不仅能观察对应的进程的执行,甚至能更改对应进程的内存和寄存器的值
大名鼎鼎的GDB就是基于ptrace实现的
著名的strace也是基于ptrace实现的
使用man
可以查看ptrace的描述
它的原型:
long ptrace(enum __ptrace_request request, pid_t pid, void *adddr, void *data);
第一个参数是一个枚举类型,在manpage
里有详细的描述,里面最特殊的一个成员是PTRACE_TRACEME
ptrace建立起一个trace的关系,其中,tracer监听tracee
ptrace的第一个参数中,除了PTRACE_TRACEME
由tracee调用外,其他的全部都是tracer调用的
PTRACE_TRACEME
的作用是,让父进程和自己之间建立trace的关系
GDB可以通过gdb pathname
的方式对某个程序进行debug
它的原理就是使用PTRACE_TRACEME
,首先fork一个子进程,子进程再调用ptrace,使用该参数让父进程trace自己,最后调用exec
系列的系统调用
tracee每当接收到信号的时候,都会停止,并返回到父进程,而父进程可以使用wait
系列的系统调用来接收对应的信息
GDB里的单步调试的实现原理也差不多:对进行单步调试的程序,将其下一条指令的内容更改为int 3
,即产生一个软中断,同时保存该位置的指令内容,程序运行到此处时,便会停止,并发出中断信号,此时,再恢复原来的指令,如此,便实现了单步调试
单步调试在ptrace中有一个对应的参数PTRACE_SINGLESTEP
,自动完成上面