本帖最后由 ggggmllll 于 2022-11-21 16:11 编辑
lz萌新一枚,本帖内容如有错误,欢迎指教。。。
本帖目录:
1,ptrace函数简介
2,PTRACE_ATTACH,PTRACE_CONT,PTRACE_DETACH使用介绍
1,ptrace函数简介:
以下是linux manpage中对ptrace函数的介绍:
The ptrace() system call provides a means by which one process
(the "tracer") may observe and control the execution of another
process (the "tracee"), and examine and change the tracee's
memory and registers. It is primarily used to implement
breakpoint debugging and system call tracing.
A tracee first needs to be attached to the tracer. Attachment
and subsequent commands are per thread: in a multithreaded
process, every thread can be individually attached to a
(potentially different) tracer, or left not attached and thus not
debugged. Therefore, "tracee" always means "(one) thread", never
"a (possibly multithreaded) process". Ptrace commands are always
sent to a specific tracee using a call of the form
ptrace(PTRACE_foo, pid, ...)
where pid is the thread ID of the corresponding Linux thread.
(Note that in this page, a "multithreaded process" means a thread
group consisting of threads created using the clone(2)
CLONE_THREAD flag.)
A process can initiate a trace by calling fork(2) and having the
resulting child do a PTRACE_TRACEME, followed (typically) by an
execve(2). Alternatively, one process may commence tracing
another process using PTRACE_ATTACH or PTRACE_SEIZE.
While being traced, the tracee will stop each time a signal is
delivered, even if the signal is being ignored. (An exception is
SIGKILL, which has its usual effect.) The tracer will be
notified at its next call to waitpid(2) (or one of the related
"wait" system calls); that call will return a status value
containing information that indicates the cause of the stop in
the tracee. While the tracee is stopped, the tracer can use
various ptrace requests to inspect and modify the tracee. The
tracer then causes the tracee to continue, optionally ignoring
the delivered signal (or even delivering a different signal
instead).
If the PTRACE_O_TRACEEXEC option is not in effect, all successful
calls to execve(2) by the traced process will cause it to be sent
a SIGTRAP signal, giving the parent a chance to gain control
before the new program begins execution.
When the tracer is finished tracing, it can cause the tracee to
continue executing in a normal, untraced mode via PTRACE_DETACH.
函数原型:
- long ptrace(enum __ptrace_request request, pid_t pid,void *addr, void *data);
- //request:一个枚举值,决定具体调用ptrace函数族的哪一个函数
- //pid:被调试进程的pid
- //addr,data:本篇教程暂不涉及
复制代码
ptrace 标准库函数实际上调用的是系统调用(syscall) __NR_ptrace ; 系统调用号 26 ;该函数是一个系统调用方法 , 可以监视进程执行 , 查看 / 更改 被监视进程的 内存 和 寄存器 情况 , 常用于断点调试 ;
注意,android在使用ptrace系统调用时,必须要有system或root权限
2,PTRACE_ATTACH,PTRACE_CONT,PTRACE_DETACH使用介绍:
PTRACE_ATTACH : 指明要附着的进程 ;
进程 A 要 调试进程 B , 在进程 A 中 先通过 ptrace 函数 附着进程 B , 传入 PTRACE_ATTACH 作为第一参数 ,调用 ptrace 函数时 , 会调用系统内核层 , 给进程 A 一个权限 , 将被调试进程 B 的控制权限交给 进程 A ;进程 A 调试 进程 B 时 , 进程 B 被挂起 , 进程 B 的 CPU 和 内存信息 , 都会被保存到内存中 , 进程 B 处于休眠状态 , CPU 不会运行 进程 B 的任何指令 ;
具体代码:
- pthread_mutex_t mutex;
- int ptrace_attach(pid_t pid)
- {
- pthread_mutex_lock(&mutex);
- if (ptrace(PTRACE_ATTACH, pid, NULL, 0) < 0)
- {
- perror("failed on ptrace_attach()");
- return -1;
- }
- waitpid(pid, NULL, WUNTRACED);
- pthread_mutex_unlock(&mutex);
- return 0;
- }
复制代码
其中,非常重要的一点就是,在进行PTRACE_ATTACH操作之前,需要互斥操作(据说暂停进程也可以,但没试过),否则会出现ptrace attach busy的错误(lz就掉进过这个坑 )
PTRACE_CONT : ptrace attach进程完毕之后 , 退出调试 , 为了程序继续向后执行 , 使用 PTRACE_CONT 作为 ptrace 函数的 第一参数即可 ;
具体代码:
- int ptrace_cont(pid_t pid)
- {
- if (ptrace(PTRACE_CONT, pid, NULL, 0) < 0)
- {
- perror("failed on ptrace_cont");
- return -1;
- }
- puts("cont sucess");
- return 0;
- }
复制代码
由于比较简单,故不叙述过多
PTRACE_DETACH:要脱离的进程 ;
进程 A 如果调用 ptrace 函数 , 传入 PTRACE_DETACH , 就会释放权限 , 发出信号 , 进程 B 恢复运行 ; 具体代码: - int ptrace_detach(pid_t pid)
- {
- if (ptrace(PTRACE_DETACH, pid, NULL, 0) < 0)
- {
- perror("failed on ptrace_detach");
- return -1;
- }
- return 0;
- }
复制代码
虽然也比较简单,但lz本人从来本人从来没成功过
码字不易,喜欢的话可以点个赞支持一下 
|