diff --git a/main.c b/main.c index d09b8ce..84db31c 100644 --- a/main.c +++ b/main.c @@ -84,13 +84,13 @@ void hook_process_invoke(char *program, char **argv, char **envp) { for (size_t i = 0;; i++) { if (argv[i] == NULL) break; - printf("==> argv[%zu]=%s\n", i, argv[i]); - } - for (size_t i = 0;; i++) { - if (envp[i] == NULL) - break; - printf("==> envp[%zu]=%s\n", i, envp[i]); + printf(" argv[%zu]=%s\n", i, argv[i]); } + // for (size_t i = 0;; i++) { + // if (envp[i] == NULL) + // break; + // printf("==> envp[%zu]=%s\n", i, envp[i]); + // } for (size_t i = 0;; i++) { if (argv[i] == NULL) @@ -120,70 +120,53 @@ static void tracee(int argc, char **argv) { die("tracee start failed: %m"); } -static void tracer(pid_t pid) { +static void tracer(pid_t ppid) { int status = 0; - // preliminary stop - // works for both SIGSTOP of the main tracee - // as well as their children when stopped by ptrace trace fork - if (waitpid(pid, &status, 0) < 0) + if (waitpid(ppid, &status, 0) < 0) die("waitpid failed: %m"); - if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) { - kill(pid, SIGKILL); - die("tracer: unexpected wait status: %x", status); - } - // capture these "fork" syscalls - // and then capture execve syscall - // fork vfork clone clone3 unsigned long ptrace_options = PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACESYSGOOD; - if (ptrace(PTRACE_SETOPTIONS, pid, NULL, ptrace_options) < 0) { + if (ptrace(PTRACE_SETOPTIONS, ppid, NULL, ptrace_options) < 0) { perror("ptrace(PTRACE_SETOPTIONS)"); - ptrace(PTRACE_DETACH, pid, NULL, NULL); - die("bruh bruh cannot trace pid %d", pid); + ptrace(PTRACE_DETACH, ppid, NULL, NULL); + die("bruh bruh cannot trace pid %d", ppid); } - ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status)); + ptrace(PTRACE_SYSCALL, ppid, 0, 0); - int sysenter = 0; while (1) { - ptrace(PTRACE_SYSCALL, pid, 0, 0); - waitpid(pid, &status, __WALL); + pid_t pid = waitpid(-1, &status, __WALL); if (WIFEXITED(status) || WIFSIGNALED(status)) { - printf("[%d] child ded\n", pid); - break; + // printf("[%d] child ded\n", pid); + if (pid == ppid) { + // the main process dies + break; + } + continue; } if (!WIFSTOPPED(status)) { printf("[%d] what's this?\n", pid); - // ptrace(PTRACE_CONT, pid, 0, 0); + ptrace(PTRACE_CONT, pid, 0, 0); continue; } // special events handled first - if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) { - printf("[%d] clone\n", pid); - // ptrace(PTRACE_CONT, pid, 0, 0); - continue; - } - if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8))) { - printf("[%d] fork\n", pid); - // ptrace(PTRACE_CONT, pid, 0, 0); - continue; - } - if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK << 8))) { - printf("[%d] vfork\n", pid); + if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)) || + status >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)) || + status >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8))) { int spawn_pid; if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &spawn_pid) == -1) { die("can't get lower child pid\n"); } - printf("=> %d\n", spawn_pid); - tracer(spawn_pid); + // printf("[%d] spawn => %d\n", pid, spawn_pid); - // ptrace(PTRACE_CONT, pid, 0, 0); + ptrace(PTRACE_SYSCALL, spawn_pid, 0, 0); + ptrace(PTRACE_SYSCALL, pid, 0, 0); continue; } @@ -192,35 +175,39 @@ static void tracer(pid_t pid) { ptrace(PTRACE_GETEVENTMSG, pid, 0, &event_msg); if (WSTOPSIG(status) == (SIGTRAP | 0x80)) { - if (sysenter) { - sysenter = 1; - continue; - } - struct user_regs_struct regs; if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1) { die("Cannot get registers"); - return; + continue; + } + + if (regs.rax != -ENOSYS) { + // syscall exit + ptrace(PTRACE_SYSCALL, pid, 0, 0); + continue; } - int syscall = regs.orig_rax; const int EXECVE_SYSCALL = 59; - if (syscall == EXECVE_SYSCALL) { - sysenter = 1; + const int EXECVEAT_SYSCALL = 322; + + int syscall = regs.orig_rax; + if (syscall == EXECVE_SYSCALL || syscall == EXECVEAT_SYSCALL) { printf("[%d] execve %d\n", pid, syscall); - // RDI: const char *filename - // RSI: char *const argv[] - // RDX: char *const envp[] - char *program; - read_string_ptrace(pid, (void *)regs.rdi, &program); - char **argv; - read_string_array_ptrace(pid, (void *)regs.rsi, &argv); - char **envp; - read_string_array_ptrace(pid, (void *)regs.rdx, &envp); + + if (syscall == EXECVE_SYSCALL) { + read_string_ptrace(pid, (void *)regs.rdi, &program); + read_string_array_ptrace(pid, (void *)regs.rsi, &argv); + read_string_array_ptrace(pid, (void *)regs.rdx, &envp); + } + if (syscall == EXECVEAT_SYSCALL) { + read_string_ptrace(pid, (void *)regs.rsi, &program); + read_string_array_ptrace(pid, (void *)regs.rdx, &argv); + read_string_array_ptrace(pid, (void *)regs.r10, &envp); + } hook_process_invoke(program, argv, envp); @@ -228,7 +215,14 @@ static void tracer(pid_t pid) { free(argv); free(envp); } + + // TODO: capture other syscalls also + // renameat -> track file renames + // printf("syscall %d\n", syscall); } + + // ask to wait for syscall of the currently stopped process + ptrace(PTRACE_SYSCALL, pid, 0, 0); } }