我有一个二进制文件,我需要从中截取某个系统调用(在本例中为unlinkat
,然后使其不执行任何操作。我有以下代码对单个进程有效;但是,将PTRACE_O_TRACECLONE
添加到ptrace opts中之后,在Tracee调用clone
之后,waitpid
调用将永远挂起。我已经在Internet的不同部分上拉了好几天的头发,以至于我遍历了strace的源头,并且实际上已经将stra进行了追踪,以查看我所追踪的是什么。
这里是来源-我删除了一些东西,以使其尽可能地减少可读性。
#define _POSIX_C_SOURCE 200112L // std (i think) #include <errno.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // linux #include <sys/ptrace.h> #include <sys/reg.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/user.h> #include <sys/wait.h> #include <unistd.h> #define OPTS PTRACE_O_TRACESYSGOOD // | PTRACE_O_TRACECLONE | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEFORK #define WOPTS 0 /* The TRACEE. Executes the process we want to target with PTRACE_TRACEME */ int do_child(int argc, char **argv) { char *args[argc + 1]; memcpy(args, argv, argc * sizeof(char *)); args[argc] = NULL; ptrace(PTRACE_TRACEME); kill(getpid(), SIGSTOP); return execvp(args[0], args); } /* Waits for the next syscall and checks to see if the process has been exited */ int wait_for_syscall(pid_t child) { int status; while (1) { ptrace(PTRACE_SYSCALL, child, 0, 0); waitpid(child, &status, WOPTS); // <--- THIS CALL HANGS FOREVER AFTER CLONE if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) return 0; if (WIFEXITED(status)) return 1; } return -1; // unreachable } /* The TRACER. Takes the pid of the child process that we just started and actually does the PTRACE stuff by passing signals back and forth to that process. */ int do_trace(pid_t child) { int status, syscall; waitpid(child, &status, WOPTS); ptrace(PTRACE_SETOPTIONS, child, 0, (unsigned long)OPTS); while (1) { // ptrace(PTRACE_SYSCALL) really needs to be called twice, first is before entry second is after exit, but idgaf if (wait_for_syscall(child) != 0) { break; } syscall = ptrace(PTRACE_PEEKUSER, child, sizeof(long) * ORIG_RAX); switch (syscall) { case SYS_clone: fprintf(stderr, "DEBUG: clone detected\n"); break; case SYS_unlinkat: fprintf(stderr, "DEBUG: unlinkat detected\n"); ptrace(PTRACE_POKEUSER, child, sizeof(long) * RAX, 0); break; } } return 0; } int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Usage: %s prog args\n", argv[0]); exit(1); } pid_t child = fork(); if (child == 0) { return do_child(argc - 1, argv + 1); } else { return do_trace(child); } return 0; }
作为免责声明,我不是C开发人员,这些天我主要是写Python,所以很多都是从我发现的不同教程中复制并粘贴的,基本上我添加/删除了随机的东西,直到gcc没有给出我有很多警告。
根据我所读的内容,我怀疑问题是有关向所涉及的流程发出信号并等待SIGTRAP的事情,我只是对该级别的操作没有真正的直觉。
我有一个二进制文件,我需要从中截取特定的系统调用-在这种情况下为unlinkat-并且使其不执行任何操作。我有以下代码对单个进程有效;但是,使用...
解决方案改用libseccomp
。