diff --git a/include/process.h b/include/process.h index 7a6dbb4..d24fa0b 100644 --- a/include/process.h +++ b/include/process.h @@ -3,6 +3,7 @@ #include #include +#include typedef enum { UNINTERRUPTABLE_SLEEP = 'D', @@ -62,6 +63,9 @@ 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); +// calculate correct instruction pointer address for hijacking +uintptr_t process_calculate_ip(process_status_t* thread, uintptr_t addr); + // read registers of thread. returns 0 on success, 1 on error int process_read_registers(process_status_t* thread, struct user_regs_struct* regs); diff --git a/src/dummy_destination.s b/src/dummy_destination.s index 19b7e9d..6a28f67 100644 --- a/src/dummy_destination.s +++ b/src/dummy_destination.s @@ -2,12 +2,12 @@ .text hijack_destination: - leaq redirect_msg(%rip), %rdi + lea redirect_msg(%rip), %rdi call puts .sleep_loop: mov $0x1, %edi call sleep jmp .sleep_loop - .section rodata -redirect_msg: .string "thread has been redirected to this function! cool!" + .section .rodata +redirect_msg: .asciz "thread has been redirected to this function! cool!" diff --git a/src/dummy_target.c b/src/dummy_target.c index 2f4742e..1b0194a 100644 --- a/src/dummy_target.c +++ b/src/dummy_target.c @@ -1,6 +1,10 @@ +#define _DEFAULT_SOURCE #include #include #include +#include +#include +#include #include extern char *program_invocation_name; @@ -51,8 +55,36 @@ __attribute__((noreturn)) void* slave3_job(void*) extern void hijack_destination(); +static struct sigaction sigill_old; +static struct sigaction sigsegv_old; +static void sigaction_handler(int signum, siginfo_t* info, void*) +{ + fprintf(stderr, "got signal %d\n", signum); + fprintf(stderr, "rip %p\n", info->si_addr); + + exit(1); +} + int main() { + // lets install some signal handlers + // for sigsegv and sig illegal instruction + struct sigaction sa; + + // sigill + memset(&sa, '\0', sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = sigaction_handler; + sigaction(SIGILL, &sa, &sigill_old); + + // sigsegv + memset(&sa, '\0', sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = sigaction_handler; + sigaction(SIGSEGV, &sa, &sigsegv_old); + status("master"); printf("hijack_destination: %p\n", hijack_destination); diff --git a/src/main.c b/src/main.c index 9889fc2..16bb1c6 100644 --- a/src/main.c +++ b/src/main.c @@ -98,7 +98,7 @@ int main(int argc, char** argv) 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; + regs.rip = process_calculate_ip(active, (uintptr_t)destination); if (process_write_registers(active, ®s)) fprintf(stderr, "failed to write registers: %s\n", strerror(errno)); diff --git a/src/process.c b/src/process.c index 94db12b..a494477 100644 --- a/src/process.c +++ b/src/process.c @@ -283,6 +283,14 @@ void process_detach_all(process_status_t* threads, size_t thread_count) while (thread_count--) ptrace(PTRACE_DETACH, threads[thread_count].pid, NULL, NULL); } +// hardcoded syscall instruction size +#define BJ_PTRACE_CONT_OFFSET 2 + +uintptr_t process_calculate_ip(process_status_t* thread, uintptr_t addr) +{ + return addr + BJ_PTRACE_CONT_OFFSET; +} + int process_read_registers(process_status_t* thread, struct user_regs_struct* regs) { struct iovec data = {