Compare commits
No commits in common. "091a8666a55a905c755d3c735c440fe75f8b947f" and "12fcd59a281b41e21041d6ba2583ac008df0a730" have entirely different histories.
091a8666a5
...
12fcd59a28
124
main.c
124
main.c
@ -84,13 +84,13 @@ void hook_process_invoke(char *program, char **argv, char **envp) {
|
|||||||
for (size_t i = 0;; i++) {
|
for (size_t i = 0;; i++) {
|
||||||
if (argv[i] == NULL)
|
if (argv[i] == NULL)
|
||||||
break;
|
break;
|
||||||
printf(" argv[%zu]=%s\n", i, argv[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 (envp[i] == NULL)
|
|
||||||
// break;
|
|
||||||
// printf("==> envp[%zu]=%s\n", i, envp[i]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (size_t i = 0;; i++) {
|
for (size_t i = 0;; i++) {
|
||||||
if (argv[i] == NULL)
|
if (argv[i] == NULL)
|
||||||
@ -120,53 +120,70 @@ static void tracee(int argc, char **argv) {
|
|||||||
die("tracee start failed: %m");
|
die("tracee start failed: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tracer(pid_t ppid) {
|
static void tracer(pid_t pid) {
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (waitpid(ppid, &status, 0) < 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)
|
||||||
die("waitpid failed: %m");
|
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 |
|
unsigned long ptrace_options = PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK |
|
||||||
PTRACE_O_TRACEVFORK | PTRACE_O_TRACESYSGOOD;
|
PTRACE_O_TRACEVFORK | PTRACE_O_TRACESYSGOOD;
|
||||||
|
|
||||||
if (ptrace(PTRACE_SETOPTIONS, ppid, NULL, ptrace_options) < 0) {
|
if (ptrace(PTRACE_SETOPTIONS, pid, NULL, ptrace_options) < 0) {
|
||||||
perror("ptrace(PTRACE_SETOPTIONS)");
|
perror("ptrace(PTRACE_SETOPTIONS)");
|
||||||
ptrace(PTRACE_DETACH, ppid, NULL, NULL);
|
ptrace(PTRACE_DETACH, pid, NULL, NULL);
|
||||||
die("bruh bruh cannot trace pid %d", ppid);
|
die("bruh bruh cannot trace pid %d", pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrace(PTRACE_SYSCALL, ppid, 0, 0);
|
ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status));
|
||||||
|
|
||||||
|
int sysenter = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
pid_t pid = waitpid(-1, &status, __WALL);
|
ptrace(PTRACE_SYSCALL, pid, 0, 0);
|
||||||
|
waitpid(pid, &status, __WALL);
|
||||||
|
|
||||||
if (WIFEXITED(status) || WIFSIGNALED(status)) {
|
if (WIFEXITED(status) || WIFSIGNALED(status)) {
|
||||||
// printf("[%d] child ded\n", pid);
|
printf("[%d] child ded\n", pid);
|
||||||
if (pid == ppid) {
|
break;
|
||||||
// the main process dies
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WIFSTOPPED(status)) {
|
if (!WIFSTOPPED(status)) {
|
||||||
printf("[%d] what's this?\n", pid);
|
printf("[%d] what's this?\n", pid);
|
||||||
ptrace(PTRACE_CONT, pid, 0, 0);
|
// ptrace(PTRACE_CONT, pid, 0, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// special events handled first
|
// special events handled first
|
||||||
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)) ||
|
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
|
||||||
status >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)) ||
|
printf("[%d] clone\n", pid);
|
||||||
status >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8))) {
|
// 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);
|
||||||
int spawn_pid;
|
int spawn_pid;
|
||||||
if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &spawn_pid) == -1) {
|
if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &spawn_pid) == -1) {
|
||||||
die("can't get lower child pid\n");
|
die("can't get lower child pid\n");
|
||||||
}
|
}
|
||||||
// printf("[%d] spawn => %d\n", pid, spawn_pid);
|
printf("=> %d\n", spawn_pid);
|
||||||
|
tracer(spawn_pid);
|
||||||
|
|
||||||
ptrace(PTRACE_SYSCALL, spawn_pid, 0, 0);
|
// ptrace(PTRACE_CONT, pid, 0, 0);
|
||||||
ptrace(PTRACE_SYSCALL, pid, 0, 0);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,41 +192,35 @@ static void tracer(pid_t ppid) {
|
|||||||
ptrace(PTRACE_GETEVENTMSG, pid, 0, &event_msg);
|
ptrace(PTRACE_GETEVENTMSG, pid, 0, &event_msg);
|
||||||
|
|
||||||
if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
|
if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
|
||||||
|
if (sysenter) {
|
||||||
|
sysenter = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
struct user_regs_struct regs;
|
struct user_regs_struct regs;
|
||||||
if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1) {
|
if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1) {
|
||||||
// TODO: this reaches, even though the stop reason is syscall
|
die("Cannot get registers");
|
||||||
// printf("error=%d pid=%d\n", errno, pid);
|
return;
|
||||||
printf("Cannot get registers\n");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regs.rax != -ENOSYS) {
|
|
||||||
// syscall exit
|
|
||||||
ptrace(PTRACE_SYSCALL, pid, 0, 0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int EXECVE_SYSCALL = 59;
|
|
||||||
const int EXECVEAT_SYSCALL = 322;
|
|
||||||
|
|
||||||
int syscall = regs.orig_rax;
|
int syscall = regs.orig_rax;
|
||||||
if (syscall == EXECVE_SYSCALL || syscall == EXECVEAT_SYSCALL) {
|
const int EXECVE_SYSCALL = 59;
|
||||||
|
if (syscall == EXECVE_SYSCALL) {
|
||||||
|
sysenter = 1;
|
||||||
printf("[%d] execve %d\n", pid, syscall);
|
printf("[%d] execve %d\n", pid, syscall);
|
||||||
|
|
||||||
char *program;
|
// RDI: const char *filename
|
||||||
char **argv;
|
// RSI: char *const argv[]
|
||||||
char **envp;
|
// RDX: char *const envp[]
|
||||||
|
|
||||||
if (syscall == EXECVE_SYSCALL) {
|
char *program;
|
||||||
read_string_ptrace(pid, (void *)regs.rdi, &program);
|
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);
|
char **argv;
|
||||||
}
|
read_string_array_ptrace(pid, (void *)regs.rsi, &argv);
|
||||||
if (syscall == EXECVEAT_SYSCALL) {
|
|
||||||
read_string_ptrace(pid, (void *)regs.rsi, &program);
|
char **envp;
|
||||||
read_string_array_ptrace(pid, (void *)regs.rdx, &argv);
|
read_string_array_ptrace(pid, (void *)regs.rdx, &envp);
|
||||||
read_string_array_ptrace(pid, (void *)regs.r10, &envp);
|
|
||||||
}
|
|
||||||
|
|
||||||
hook_process_invoke(program, argv, envp);
|
hook_process_invoke(program, argv, envp);
|
||||||
|
|
||||||
@ -217,14 +228,7 @@ static void tracer(pid_t ppid) {
|
|||||||
free(argv);
|
free(argv);
|
||||||
free(envp);
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user