ptrace是所有调试和跟踪程序所用的基础,包括gdb,strace,ltrace等工具。ptrace也用于反调试,因为对于一个线程ptrace之后便不能再ptrace。ptrace有2种启动方式:
- 在子进程中ptrace通知父进程调试自己
- 从一个进程对另一个进程进行ptrace
因此ptrace的结构也分为3种(网上收集):
- 父进程调试子进程
int pid=fork()
if(pid == -1)
{
}
else if(pid == 0)//子进程
{
ptrace(PTRACE_TRACEME,0,0,0);
}
else//父进程
{
wait(0);
}
- 子进程调试父进程
pid_t pid = fork();
assert(pid != -1);
int status;
long readme = 0;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme));
}
- A进程调试B进程
同时,下面2种情况测试失败:
- ptrace自身
- 互相ptrace
反反调试的构思(用户态):由于不存在环回ptrace,因此对于由于已经ptrace而无法调试的程序,找到第一个发出ptrace的进程(/proc/self/status TracerPid),注入并执行ptrace DETACH,之后对下一级同样操作直到最后的子进程