ptrace选项根本不起作用

时间:2013-12-14 04:24:48

标签: c linux ptrace

当我附加到另一个进程时,我无法跟踪fork / exec事件,从waitpid返回的status始终为零(右移16次后)。

我已成功连接到bash shell,但无论我运行什么命令,状态始终为零,所以我没有捕获任何fork或exec事件:

#define PALL PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE \
    | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT

int main(int argc, char **argv)
{ 
    pid_t child = 0;
    int status = 0;

    if (argc != 2) { ... }
    child = atoi (argv[1]);
    if (ptrace (PTRACE_ATTACH, child, 0, 0) < 0) { ... }

    ptrace(PTRACE_SETOPTIONS, child, NULL, PALL);
    ptrace(PTRACE_SYSCALL, child, NULL, NULL);
    ptrace(PTRACE_CONT, child, NULL, NULL);

    while(1) {
        waitpid(child, &status, 0);
        if(WIFEXITED(status))
            break;

        status >>= 16;
        if (status != 0)
            printf ("Status: %d\n", status >> 16);

        ptrace(PTRACE_SYSCALL, child, NULL, NULL);
    }

    ptrace(PTRACE_DETACH, child, NULL, NULL);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

  

从waitpid返回的status始终为零(右移后)   16次)。

您先将status位移至16位,但先移动status >>= 16然后printf (…, status >> 16);移动32次,因此始终打印0。还有一些不太明显的缺陷:

  • 为了完整起见,我们应该处理案例WIFSIGNALED
  • 我们应该向孩子传递信号;它可能需要它们正常运行。
  • 由于我们也追踪了孩子的孩子,我们也必须wait来处理他们。
  • 紧接PTRACE_SYSCALL之前的
  • PTRACE_CONT没有意义。
  • 如果PTRACE_SETOPTIONS尚未完成,
  • PTRACE_ATTACH可能会失败,因此我们必须wait

考虑到所有这些,该程序可能看起来像

#include <stdio.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#define PALL PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE \
           | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT
int main(int argc, char **argv)
{ 
    pid_t child, pid;
    int status;
    if (argc != 2) { return 2; }
    child = atoi(argv[1]);
    if (ptrace(PTRACE_ATTACH, child, 0, 0) < 0) { return 1; }
    wait(NULL); // PTRACE_SETOPTIONS may work only after this
    ptrace(PTRACE_SETOPTIONS, child, NULL, PALL);
    ptrace(PTRACE_CONT, child, NULL, NULL);
    while (pid = wait(&status), pid > 0)
    {
        if (WIFEXITED(status) || WIFSIGNALED(status))
        {
            if (pid == child) break;
            printf("grandchild %d exited\n", pid);
            continue;
        }
        if (status>>16)
            printf("[%d] Status: %x\n", pid, status);
        int signal = WSTOPSIG(status);
        if (signal == SIGTRAP)
        {   // system call or ptrace event
            signal = 0;
            if (status>>16)
                printf("ptrace event: %d\n", status>>16);
        }
        ptrace(PTRACE_CONT, pid, 0, signal);
    }
    ptrace(PTRACE_DETACH, child, NULL, NULL);
    return 0;
}