From 197cc3098d9a97eb488f1e49e2fb71740dd64645 Mon Sep 17 00:00:00 2001 From: Michael <20937441+KMikeeU@users.noreply.github.com> Date: Sun, 17 May 2026 19:23:06 +0200 Subject: [PATCH] fix: static build + new syscall spoofer --- Makefile | 4 +- src/spoof/spoofer.c | 180 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 154 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 21319fb..997315d 100644 --- a/Makefile +++ b/Makefile @@ -71,11 +71,11 @@ host: $(HOST_EXE) $(HOST_EXE_SPOOFER) # Build the main challenge executable $(HOST_EXE): $(HOST_SRC) | build - $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_INCLUDE) $(HOST_SRC) -o $@ + $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -static $(HOST_INCLUDE) $(HOST_SRC) -o $@ # Build the spoofer $(HOST_EXE_SPOOFER): $(HOST_SRC_SPOOFER) | build - $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -shared -fPIC $^ -o $@ -ldl + $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $^ -o $@ -ldl # Build the encryptor $(HOST_EXE_ENCRYPTOR): $(HOST_SRC_ENCRYPTOR) | build diff --git a/src/spoof/spoofer.c b/src/spoof/spoofer.c index 6aebc63..bdfe917 100644 --- a/src/spoof/spoofer.c +++ b/src/spoof/spoofer.c @@ -1,40 +1,164 @@ +#define _GNU_SOURCE #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -static FILE *(*real_fopen)(const char *path, const char *mode) = NULL; - -static void init_real_fopen(void) { - if (!real_fopen) { - real_fopen = dlsym(RTLD_NEXT, "fopen"); - if (!real_fopen) { - fprintf(stderr, "proc_redirect: dlsym(fopen) failed: %s\n", dlerror()); - abort(); - } +static void write_mem(pid_t pid, unsigned long addr, const char *buf, size_t len) +{ + struct iovec local = {(void *)buf, len}; + struct iovec remote = {(void *)addr, len}; + if (process_vm_writev(pid, &local, 1, &remote, 1, 0) < 0) + { + perror("spoofer: process_vm_writev"); + abort(); } } -FILE *fopen(const char *path, const char *mode) { - init_real_fopen(); +static int read_string(pid_t pid, unsigned long addr, char *buf, size_t max) +{ + struct iovec local = {buf, max}; + struct iovec remote = {(void *)addr, max}; + ssize_t n = process_vm_readv(pid, &local, 1, &remote, 1, 0); + if (n < 0) + return -1; + buf[n < (ssize_t)max ? (size_t)n : max - 1] = '\0'; + buf[strnlen(buf, max - 1)] = '\0'; + return 0; +} - if (path && strncmp(path, "/proc/", 6) == 0) { - const char *rel_suffix = path + 1; - size_t len = strlen(rel_suffix) + 4; - char *new_path = malloc(len); - if (!new_path) { - fprintf(stderr, "proc_redirect: malloc failed\n"); - abort(); - } - new_path[0] = '.'; - new_path[1] = '/'; - new_path[2] = '.'; - strcpy(new_path + 3, rel_suffix); +static void handle_openat(pid_t pid, struct user_regs_struct *regs) +{ + unsigned long path_ptr = regs->rsi; + char orig[4096] = {0}; + if (read_string(pid, path_ptr, orig, sizeof(orig)) < 0) + return; + if (strncmp(orig, "/proc/", 6) != 0) + return; - FILE *f = real_fopen(new_path, mode); - free(new_path); - return f; + char newpath[4096]; + snprintf(newpath, sizeof(newpath), ".%s", orig + 1); + + /* Scratch space below the red zone, safe from any live stack frame */ + unsigned long scratch = regs->rsp - 256 - sizeof(newpath); + write_mem(pid, scratch, newpath, strlen(newpath) + 1); + + struct user_regs_struct r = *regs; + r.rsi = scratch; + if (ptrace(PTRACE_SETREGS, pid, NULL, &r) < 0) + perror("spoofer: PTRACE_SETREGS"); + else + fprintf(stderr, "spoofer: redirected '%s' -> '%s'\n", orig, newpath); +} + +int main(int argc, char **argv) +{ + if (argc < 2) + { + fprintf(stderr, "usage: %s [args...]\n", argv[0]); + return 1; } - return real_fopen(path, mode); + pid_t pid = fork(); + if (pid < 0) + { + perror("fork"); + return 1; + } + + if (pid == 0) + { + if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) + { + perror("spoofer: PTRACE_TRACEME"); + _exit(1); + } + execvp(argv[1], argv + 1); + perror("spoofer: execvp"); + _exit(1); + } + + int status; + if (waitpid(pid, &status, 0) < 0) + { + perror("waitpid"); + return 1; + } + if (!WIFSTOPPED(status)) + { + fprintf(stderr, "spoofer: unexpected initial status %d\n", status); + return 1; + } + + if (ptrace(PTRACE_SETOPTIONS, pid, NULL, + (void *)(long)(PTRACE_O_TRACESYSGOOD | PTRACE_O_EXITKILL)) < 0) + { + perror("spoofer: PTRACE_SETOPTIONS"); + return 1; + } + + int in_syscall = 0; + + while (1) + { + if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL) < 0) + { + perror("spoofer: PTRACE_SYSCALL"); + break; + } + if (waitpid(pid, &status, 0) < 0) + { + perror("waitpid"); + break; + } + if (WIFEXITED(status) || WIFSIGNALED(status)) + break; + if (!WIFSTOPPED(status)) + continue; + + int sig = WSTOPSIG(status); + + if (sig == (SIGTRAP | 0x80)) + { + if (!in_syscall) + { + struct user_regs_struct regs; + if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == 0) + { + if (regs.orig_rax == SYS_openat) + { + handle_openat(pid, ®s); + } + else if (regs.orig_rax == SYS_open) + { + /* SYS_open: rdi=path — copy to rsi so handle_openat works */ + regs.rsi = regs.rdi; + handle_openat(pid, ®s); + } + } + } + in_syscall ^= 1; + } + else + { + /* Forward real signals to the tracee */ + ptrace(PTRACE_SYSCALL, pid, NULL, (void *)(long)sig); + in_syscall = 0; + continue; + } + } + + if (WIFEXITED(status)) + return WEXITSTATUS(status); + if (WIFSIGNALED(status)) + return 128 + WTERMSIG(status); + return 0; }