diff --git a/include/process.h b/include/process.h index 0c40c6a..774d39d 100644 --- a/include/process.h +++ b/include/process.h @@ -55,4 +55,10 @@ int find_active_thread(process_status_t* list, size_t count, process_status_t** // check if this process has any capability or is ran as root to be able to ptrace attach int check_ptrace_permissions(); +// attach to all threads of the process. on error returns 1 and detaches from already attached +int process_attach_all(process_status_t* threads, size_t thread_count); + +// detaches from all threads +void process_detach_all(process_status_t* threads, size_t thread_count); + #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index aba5ea9..2983442 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,9 @@ #define _DEFAULT_SOURCE #include +#include #include #include +#include #include "process.h" void print_process(process_status_t* proc) @@ -69,15 +71,31 @@ int main(int argc, char** argv) puts("Active thread:"); print_process(active); - free(threads); - free(list); - if (!check_ptrace_permissions()) { fputs("this process doesn't have permission to ptrace.\n", stderr); fputs("either run as root or set caps.\n", stderr); return 1; } + + // attach + if (process_attach_all(threads, thread_count)) + { + fprintf(stderr, "failed to attach: %s\n", strerror(errno)); + + free(threads); + free(list); + + return 1; + } + + puts("attached to all threads. press any key"); + getc(stdin); + + process_detach_all(threads, thread_count); + + free(threads); + free(list); return 0; } \ No newline at end of file diff --git a/src/process.c b/src/process.c index 5339171..cde538e 100644 --- a/src/process.c +++ b/src/process.c @@ -2,6 +2,8 @@ #include "process.h" #include "debug.h" #include +#include +#include #include #include #include @@ -235,4 +237,45 @@ int check_ptrace_permissions() } return 0; +} + +int process_attach_all(process_status_t* threads, size_t thread_count) +{ + for (size_t i = 0; i < thread_count; i++) + { + pid_t pid = threads[i].pid; + if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) + { + // we've encountered error. now we must detach from attached and return 1 + process_detach_all(threads, i+1); + return 1; + } + + // now wait for thread to be stopped + int wstatus; + do { + waitpid(pid, &wstatus, 0); +#if DEBUG + if (WIFEXITED(wstatus)) { + TRACE("exited, status=%d\n", WEXITSTATUS(wstatus)); + } else if (WIFSIGNALED(wstatus)) { + TRACE("killed by signal %d\n", WTERMSIG(wstatus)); + } else if (WIFSTOPPED(wstatus)) { + TRACE("stopped by signal %d\n", WSTOPSIG(wstatus)); + } else if (WIFCONTINUED(wstatus)) { + TRACE("continued\n"); + } + +#endif + } while (!(WIFSTOPPED(wstatus) && WSTOPSIG(wstatus) == SIGSTOP)); + + // since thread is properly stopped we can continue to the next one + } + + return 0; +} + +void process_detach_all(process_status_t* threads, size_t thread_count) +{ + while (thread_count--) ptrace(PTRACE_DETACH, threads[thread_count].pid, NULL, NULL); } \ No newline at end of file