turns out you have to offset the syscall instruction to rip, because PTRACE_CONT continue process by "returning" from syscall

This commit is contained in:
mykola2312 2024-08-22 16:26:22 +03:00
parent 0ae068762f
commit 635cf023c7
5 changed files with 48 additions and 4 deletions

View file

@ -3,6 +3,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/user.h> #include <sys/user.h>
#include <stdint.h>
typedef enum { typedef enum {
UNINTERRUPTABLE_SLEEP = 'D', UNINTERRUPTABLE_SLEEP = 'D',
@ -62,6 +63,9 @@ int process_attach_all(process_status_t* threads, size_t thread_count);
// detaches from all threads // detaches from all threads
void process_detach_all(process_status_t* threads, size_t thread_count); 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 // read registers of thread. returns 0 on success, 1 on error
int process_read_registers(process_status_t* thread, struct user_regs_struct* regs); int process_read_registers(process_status_t* thread, struct user_regs_struct* regs);

View file

@ -2,12 +2,12 @@
.text .text
hijack_destination: hijack_destination:
leaq redirect_msg(%rip), %rdi lea redirect_msg(%rip), %rdi
call puts call puts
.sleep_loop: .sleep_loop:
mov $0x1, %edi mov $0x1, %edi
call sleep call sleep
jmp .sleep_loop jmp .sleep_loop
.section rodata .section .rodata
redirect_msg: .string "thread has been redirected to this function! cool!" redirect_msg: .asciz "thread has been redirected to this function! cool!"

View file

@ -1,6 +1,10 @@
#define _DEFAULT_SOURCE
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
extern char *program_invocation_name; extern char *program_invocation_name;
@ -51,8 +55,36 @@ __attribute__((noreturn)) void* slave3_job(void*)
extern void hijack_destination(); 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() 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"); status("master");
printf("hijack_destination: %p\n", hijack_destination); printf("hijack_destination: %p\n", hijack_destination);

View file

@ -98,7 +98,7 @@ int main(int argc, char** argv)
if (process_read_registers(active, &regs)) if (process_read_registers(active, &regs))
fprintf(stderr, "failed to read registers: %s\n", strerror(errno)); fprintf(stderr, "failed to read registers: %s\n", strerror(errno));
// hijack instruction pointer to our destination // 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, &regs)) if (process_write_registers(active, &regs))
fprintf(stderr, "failed to write registers: %s\n", strerror(errno)); fprintf(stderr, "failed to write registers: %s\n", strerror(errno));

View file

@ -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); 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) int process_read_registers(process_status_t* thread, struct user_regs_struct* regs)
{ {
struct iovec data = { struct iovec data = {