diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 0a36572..6050b1e 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -9,6 +9,10 @@ target_compile_options(trampoline PRIVATE -Wall -Wextra -Werror -Wpointer-arith # Link target_link_libraries(trampoline dl trampoline-headers) +# RPath +set_target_properties(trampoline PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native") +target_link_options(trampoline PRIVATE "LINKER:--disable-new-dtags") + # Install function(install_trampoline bin_dir) install(TARGETS trampoline DESTINATION "${bin_dir}") diff --git a/native/src/main.cpp b/native/src/main.cpp index ee7196e..b035338 100644 --- a/native/src/main.cpp +++ b/native/src/main.cpp @@ -3,6 +3,12 @@ #include #include #include +#include +#include +#include +#include + +#include #include "log.h" #include "memory.h" @@ -16,8 +22,30 @@ int main(__attribute__((unused)) int argc, char *argv[]) { if (pid == -1) { ERR("Unable To Fork Process: %s", strerror(errno)); } else if (pid == 0) { - // Child + // seccomp Filter + sock_filter filter[] = { + // Load Syscall Number To Accumulator + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(seccomp_data, nr)), + // If Syscall Does Not Match The Trampoline, Then Skip The Next Instruction + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, TRAMPOLINE_SYSCALL, 0, 1), + // Trigger PTrace And End Filter + BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE), + // Allow Syscall And End Filter + BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW) + }; + sock_fprog prog = { + .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])), + .filter = filter + }; + // Setup PTrace ptrace(PTRACE_TRACEME, 0, 0, 0); + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { + ERR("Unable To Prepare Process For seccomp: %s", strerror(errno)); + } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) == -1) { + ERR("Unable To Set seccomp Filter: %s", strerror(errno)); + } + // Execute Program execvp(argv[1], (char *const *) &argv[1]); ERR("Unable To Execute Program: %s: %s", argv[1], strerror(errno)); } else { @@ -26,7 +54,7 @@ int main(__attribute__((unused)) int argc, char *argv[]) { // Wait For PTrace waitpid(pid, nullptr, 0); // Configure PTrace - ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACESYSGOOD); + ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACESECCOMP); // Setup Trampoline init_memory(pid); diff --git a/native/src/memory.cpp b/native/src/memory.cpp index cf3e692..f3be9ad 100644 --- a/native/src/memory.cpp +++ b/native/src/memory.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include "memory.h" #include "log.h" @@ -11,6 +13,9 @@ void init_memory(pid_t pid) { // Read Memory void memory_reader(uint32_t guest_addr, void *data, uint32_t size) { + if (size == 0) { + return; + } iovec local[1]; local[0].iov_base = data; local[0].iov_len = size; @@ -19,7 +24,7 @@ void memory_reader(uint32_t guest_addr, void *data, uint32_t size) { remote[0].iov_len = size; ssize_t ret = process_vm_readv(guest_pid, local, 1, remote, 1, 0); if (ret != size) { - ERR("Unable To Read Data"); + ERR("Unable To Read Data: %s", strerror(errno)); } } @@ -33,6 +38,6 @@ void memory_writer(uint32_t guest_addr, void *data, uint32_t size) { remote[0].iov_len = size; ssize_t ret = process_vm_writev(guest_pid, local, 1, remote, 1, 0); if (ret != size) { - ERR("Unable To Write Data"); + ERR("Unable To Write Data: %s", strerror(errno)); } } \ No newline at end of file diff --git a/native/src/ptrace.cpp b/native/src/ptrace.cpp index d87d2f0..25e4ca7 100644 --- a/native/src/ptrace.cpp +++ b/native/src/ptrace.cpp @@ -32,10 +32,10 @@ static void safe_wait(pid_t guest_pid, int *status) { } static void ptrace_wait_syscall(pid_t guest_pid) { while (true) { - safe_ptrace(PTRACE_SYSCALL, guest_pid, nullptr, nullptr); + safe_ptrace(PTRACE_CONT, guest_pid, nullptr, nullptr); int status; safe_wait(guest_pid, &status); - if (WIFSTOPPED(status) && (WSTOPSIG(status) & 0x80)) { + if ((status >> 8) == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) { return; } } @@ -52,7 +52,7 @@ static bool check_syscall(pid_t guest_pid, arm32_pt_regs *out) { .iov_base = ®s, .iov_len = sizeof(regs) }; - safe_ptrace(PTRACE_GETREGSET, guest_pid, nullptr, ®s); + safe_ptrace(PTRACE_GETREGSET, guest_pid, (void *) NT_PRSTATUS, &io); if (io.iov_len != sizeof(regs)) { ERR("Guest Must Be 32-Bit"); } @@ -61,15 +61,22 @@ static bool check_syscall(pid_t guest_pid, arm32_pt_regs *out) { // Not Trampoline return false; } + // Block Syscall + int new_syscall = -1; + iovec syscall_io = { + .iov_base = &new_syscall, + .iov_len = sizeof(int), + }; + safe_ptrace(PTRACE_SETREGSET, guest_pid, (void *) NT_ARM_SYSTEM_CALL, &syscall_io); // Export Registers *out = regs; // Return return true; } static void get_arguments(arm32_pt_regs *regs, uint32_t *arg1, uint32_t *arg2, uint32_t *arg3) { - *arg1 = regs->regs[1]; - *arg2 = regs->regs[2]; - *arg3 = regs->regs[3]; + *arg1 = regs->regs[0]; + *arg2 = regs->regs[1]; + *arg3 = regs->regs[2]; } static void set_syscall_return(pid_t guest_pid, arm32_pt_regs *regs) { regs->regs[0] = 0; @@ -86,7 +93,7 @@ void loop_ptrace(pid_t guest_pid) { // Wait For Syscall ptrace_wait_syscall(guest_pid); - // Handle Syscall Entrance + // Handle Syscall arm32_pt_regs regs = {}; bool is_trampoline = check_syscall(guest_pid, ®s); if (is_trampoline) { @@ -100,13 +107,7 @@ void loop_ptrace(pid_t guest_pid) { // Run Trampoline uint32_t ret = trampoline(id, args); memory_writer(args_addr, &ret, sizeof(uint32_t)); - } - - // Handle Syscall Exit - ptrace_wait_syscall(guest_pid); - - // Set Syscall Return - if (is_trampoline) { + // Set Syscall Return set_syscall_return(guest_pid, ®s); } }