diff --git a/include/process.h b/include/process.h index 774d39d..e72d5bb 100644 --- a/include/process.h +++ b/include/process.h @@ -2,6 +2,7 @@ #define __PROCESS_H #include +#include typedef enum { UNINTERRUPTABLE_SLEEP = 'D', @@ -61,4 +62,10 @@ 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); +// read registers of thread. returns 0 on success, 1 on error +int process_read_registers(process_status_t* thread, struct user_regs_struct* regs); + +// write registers for thread. for return value same rules apply as read registers function +int process_write_registers(process_status_t* thread, const struct user_regs_struct* regs); + #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 2983442..910e9dc 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "process.h" @@ -89,8 +90,17 @@ int main(int argc, char** argv) return 1; } - puts("attached to all threads. press any key"); - getc(stdin); + puts("attached to all threads. please enter address of destination"); + void* destination; + scanf("%p", &destination); + + struct user_regs_struct regs; + if (process_read_registers(active, ®s)) + fprintf(stderr, "failed to read registers: %s\n", strerror(errno)); + // hijack instruction pointer to our destination + regs.rip = (uintptr_t)destination; + if (process_write_registers(active, ®s)) + fprintf(stderr, "failed to write registers: %s\n", strerror(errno)); process_detach_all(threads, thread_count); diff --git a/src/process.c b/src/process.c index cde538e..f2dc965 100644 --- a/src/process.c +++ b/src/process.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -278,4 +280,25 @@ int process_attach_all(process_status_t* threads, size_t thread_count) void process_detach_all(process_status_t* threads, size_t thread_count) { while (thread_count--) ptrace(PTRACE_DETACH, threads[thread_count].pid, NULL, NULL); +} + +int process_read_registers(process_status_t* thread, struct user_regs_struct* regs) +{ + struct iovec data = { + .iov_base = regs, + .iov_len = sizeof(struct user_regs_struct) + }; + memset(regs, '\0', sizeof(struct user_regs_struct)); + + return ptrace(PTRACE_GETREGSET, thread->pid, NT_PRSTATUS, &data) < 0; +} + +int process_write_registers(process_status_t* thread, const struct user_regs_struct* regs) +{ + struct iovec data = { + .iov_base = (void*)regs, + .iov_len = sizeof(struct user_regs_struct) + }; + + return ptrace(PTRACE_SETREGSET, thread->pid, NT_PRSTATUS, &data) < 0; } \ No newline at end of file