ptrace如何捕获fork的系统调用?

时间:2013-12-07 10:11:01

标签: c++ c linux ptrace

我尝试使用ptrace来捕获子进程系统调用id,例如execve(11)或fork(2)。

我的代码在这里。

#include <sys/syscall.h>
#include <sys/reg.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main(){
    pid_t pid;
    if ((pid = fork()) == 0){
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        pid_t t = fork();
    } else{
        int status;
        struct rusage resource;
        while (true){
            wait4(pid, &status, 0, &resource);
            if (WIFEXITED(status)) break;
            int syscall = ptrace(PTRACE_PEEKUSER, pid, 4 * ORIG_EAX, NULL);
            if (syscall == SYS_execve) printf("%d\n", syscall);
            ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
        }
    }
    return 0;
}

在我看来,程序应该在屏幕上打印“2”(因为系统调用“fork”id为2),但程序结束后我什么都没得到。 有人可以解释一下吗?

2 个答案:

答案 0 :(得分:1)

如果你的程序已经正常退出,那么

if (WIFEXITED(status)) break;

这句话可能导致不打印2,因为它将其从循环中取出。

请参阅此声明。

答案 1 :(得分:0)

Op现在可能不需要答案了,但是其他人可能需要,所以我就把它放在那里。

首先,只有在执行if (syscall == SYS_execve)系统调用时,行execv才有效。这意味着它将打印分配给execv的系统调用号码,该号码在我的机器(x86)中为号码11。但是您实际上从未调用过execv,因此什么也不会打印。

其次,您可能看不到屏幕上显示2的原因是,如果您使用的是2.3.3版或更高版本,则fork()调用实际上不是系统调用。 不会调用kernel's fork(),而是调用glibc fork()包装器函数,它实际上不是系统调用。

然后,此函数将调用clone()系统调用。因此,如果要捕获它并对其进行操作,则需要搜索克隆系统调用ID(取决于您使用的版本)或使用SYS_clone。

来源:http://man7.org/linux/man-pages/man2/fork.2.html