admin 发表于 6 天前

svc hook框架

受看雪里所有svc hook思路启发
根据返回指针地址判断是否为劫持svc
仅支持aarch64
仿inlinehook框架结构
不依靠root
代码ai写的 自己优化
可以直接编译使用
seccomp bpf有意思的玩法:
后门
提前设置一个svc被劫持
,保存自己syscall的地址为instruction_pointer
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, instruction_pointer)),
当执行该syscall时seccomp进入自己的函数
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP)
或者触发
SECCOMP_RET_KILL
该kill只传递信号 不能被捕捉到svc 所以一切针对svc的hook无效#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <stdatomic.h>
// http://aospxref.com/android-13.0.0_r3/s?path=asm/sigcontext.h&project=bionic
#include <asm/sigcontext.h>
#include <setjmp.h>
#if defined(__aarch64__)
#include "syscalls_aarch64.h"
const char *const *syscall_table = &kSyscalls_Aarch64;
#elif defined(__x86_64__)
#include "syscalls_x86_64.h"
const char *const *syscall_table = &kSyscalls_x86_64;
#endif
__inline__ __attribute__((always_inline))__attribute__ ((visibility ("hidden")))long my_syscall(long __number, ...);
typedef long (*hook_function_t)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);

#define MAX_SYSCALL_NO 1024

void sigsys_handler(int sig, siginfo_t *info, void *secret);
typedef struct RemoteCaller {
pthread_rwlock_t rwlock_;
    pthread_mutex_t caller_mutex_;
    pthread_cond_t caller_cond_;
    pthread_mutex_t callee_mutex_;
    pthread_cond_t callee_cond_;
atomic_long call_result_;
    atomic_int syscall_no_;
    atomic_bool start_loop_;
_Atomic(struct sigcontext *) call_args_; // 修改为原子指针类型
   atomic_bool signal_received_;
   atomic_bool signal_received_1;
   atomic_bool signal_received_2;
    hook_function_t before_hook_func_;
    hook_function_t after_hook_func_;
    hook_function_t patch_func_;
pthread_barrier_t barrier_;
} RemoteCaller;

_Atomic(RemoteCaller *)* g_remote_caller = {0};

void trace_sys_call(int sysno) {
    printf("===== handle syscall no %d : %s\n", sysno, syscall_table);
}

void RemoteCaller_handleSigsys();
void RemoteCaller_start_remote_thread(_Atomic(RemoteCaller *) caller);
/*void RemoteCaller_start_remote_thread(RemoteCaller *caller);*/
long RemoteCaller_remote_syscall( _Atomic(RemoteCaller *) caller, struct sigcontext* sigctx);
//l*long RemoteCaller_remote_syscall( RemoteCaller *caller, struct sigcontext* sigctx);*/
RemoteCaller* RemoteCaller_create(int syscall_no, void *before_hook_func, void *after_hook_func, void *patch_func) {


_Atomic(RemoteCaller *) caller = ATOMIC_VAR_INIT(malloc(sizeof(RemoteCaller)));
if (caller == NULL) {
}


   /* RemoteCaller *caller = (RemoteCaller *) malloc(sizeof(RemoteCaller));
   
/*if (caller == NULL) {
      return NULL;
    }*/
    caller->caller_mutex_ = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
    caller->caller_cond_ = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
   
    caller->callee_mutex_ = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
    caller->callee_cond_ = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
    pthread_barrier_init(&caller->barrier_, NULL, 2);
    atomic_init(&caller->call_result_, 0);
    atomic_init(&caller->syscall_no_, syscall_no);
   caller->start_loop_ = false;
//caller->start_loop_ = true;
    caller->before_hook_func_ = (hook_function_t) before_hook_func;
    caller->after_hook_func_ = (hook_function_t) after_hook_func;
    caller->patch_func_ = (hook_function_t) patch_func;
    RemoteCaller_handleSigsys();
    RemoteCaller_start_remote_thread(atomic_load(&caller));
    return atomic_load(&caller);
}




RemoteCaller* RemoteCaller_getInstance(int syscall_no) {
    if (syscall_no > MAX_SYSCALL_NO - 1 || syscall_no < 0) {
      printf("syscall_no %d error\n", syscall_no);
      abort();
      return NULL;
    }
    _Atomic(RemoteCaller *) *atomic_caller = &g_remote_caller;
    // 使用原子操作获取g_remote_caller
    _Atomic(RemoteCaller *) *caller = atomic_load(atomic_caller);
    if (caller == NULL) {
      // 如果不存在,调用RemoteCaller_create创建一个
      caller = RemoteCaller_create(syscall_no, NULL, NULL, NULL);
    }
    return caller;
}
void RemoteCaller_registerSyscall(int syscall_no, void *before_hook_func, void *after_hook_func, void *patch_func) {
    if (syscall_no > MAX_SYSCALL_NO - 1 || syscall_no < 0) {
      printf("syscall_no %d error\n", syscall_no);
      return;
    }
_Atomic(RemoteCaller *) *atomic_caller = &g_remote_caller;
   _Atomic(RemoteCaller *) * old_val = NULL;
    _Atomic(RemoteCaller *) new_val = RemoteCaller_create(syscall_no, before_hook_func, after_hook_func, patch_func);
    atomic_compare_exchange_strong(atomic_caller, &old_val, new_val);

    // If the atomic pointer to RemoteCaller was already set, free the new RemoteCaller object.
    if (old_val != NULL) {
      free(new_val);
    }
}


_Atomic(bool) RemoteCaller_handle_sigsys_ = false;
//bool RemoteCaller_handle_sigsys_ = false;

jmp_buf env;
void sigsys_handler1(int sig, siginfo_t *info, void *secret) {

      


    ucontext_t *ctx = (ucontext_t *) secret;
    struct sigcontext *sigctx = (struct sigcontext *) &ctx->uc_mcontext;
    bool is_handle_syscall = false;
#if defined(__aarch64__)
    is_handle_syscall = *(((uint32_t *) info->si_call_addr) - 1) == 0xd4000001; //01 00 00 d4svc   #0
    int sysno = sigctx->regs;
    unsigned long *presult = (unsigned long *) &sigctx->regs;
#else
    printf("unsupport arch\n");
//    exit(0);
#endif
    if (is_handle_syscall) {
_Atomic(RemoteCaller *) caller = RemoteCaller_getInstance(sysno);
      if (caller == NULL) {
            printf("remote caller for syscall %d not found\n", sysno);
      }
      long ret = RemoteCaller_remote_syscall(caller, sigctx);
      *presult = ret;
    }
}


int is_address_valid(void* ptr) {
setjmp(env);
printf("The pointer is invalid.\n");
}
void RemoteCaller_handleSigsys1() {
/*   if (!atomic_load(&RemoteCaller_handle_sigsys_)) {*/
      printf("register SIGSYS start\n");
      struct sigaction act;
      struct sigaction old_act;
      sigemptyset(&act.sa_mask);
      act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_SIGINFO;
      act.sa_sigaction = sigsys_handler;
      sigaction(SIGSYS, &act, &old_act);
      atomic_store(&RemoteCaller_handle_sigsys_, true);
      printf("register SIGSYS end\n");
/*   }*/
}


unsigned long *RemoteCaller_get_syscall_param(struct sigcontext *sigctx, int index) {
    if (index < 0 || index >= 6) return 0;
    unsigned long *regs = NULL;
    unsigned long *sp = NULL;
   
#if defined(__aarch64__)
    regs = (ucontext_t *) &(sigctx->regs);
    sp = (ucontext_t *) sigctx->sp;
    if (index <= 7) {
      // x0 - x7
      return regs;
    } else {
      // stack
      return sp;
    }
#else
    printf("unsupport arch");
//    exit(0);
#endif
}

void* RemoteCaller_remote_call_thread_function(void *args_ptr) {
//printf(">>>>> handle signal not caused by ebpf\n");
//    RemoteCaller *caller = (RemoteCaller *) args_ptr;
_Atomic(RemoteCaller *) caller = atomic_load((_Atomic(RemoteCaller *) *) &args_ptr);

// 发送信号
atomic_store(&caller->signal_received_2, true);
pthread_cond_signal(&caller->caller_cond_);
pthread_mutex_lock(&caller->callee_mutex_);
    while (atomic_load(&caller->start_loop_)) {
      printf("## RemoteCaller wait call\n");
while (!atomic_load(&caller->signal_received_1)) {
    pthread_cond_wait(&caller->callee_cond_, &caller->callee_mutex_);
}
// 重置信号标志
atomic_store(&caller->signal_received_1, false);
pthread_mutex_unlock(&caller->callee_mutex_);
      printf("## RemoteCaller wait call\n");
    atomic_store(&caller->call_result_, syscall(caller->syscall_no_,
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 0),
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 1),
                //         0,
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 2),
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 3),
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 4),
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 5),
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 6),
                               RemoteCaller_get_syscall_param(atomic_load(&caller->call_args_), 7)
                               ));

                                 
                                       
                                             trace_sys_call(caller->syscall_no_);
      printf("## RemoteCaller wake call thread\n");
// 发送信号
atomic_store(&caller->signal_received_, true);

pthread_cond_signal(&caller->caller_cond_);

    }
    return NULL;
}



// 使用barrier同步线程

void RemoteCaller_start_remote_thread(_Atomic(RemoteCaller *) caller_atomic) {
    _Atomic(RemoteCaller *) caller = atomic_load(&caller_atomic);
    if (!atomic_load(&caller->start_loop_)) {
      atomic_store(&caller->start_loop_, true);
      printf("start remote thread for syscall no %d\n", caller->syscall_no_);

      pthread_t td;
      int rc = pthread_create(&td, NULL, RemoteCaller_remote_call_thread_function, caller);
      if (rc != 0) {
            printf("Failed to create remote call thread for syscall no %d\n", caller->syscall_no_);
            return;
      }
      pthread_detach(td);
pthread_mutex_lock(&caller->caller_mutex_);
      while (!atomic_load(&caller->signal_received_2)) {
            pthread_cond_wait(&caller->caller_cond_, &caller->caller_mutex_);
            break;
      }

      // 重置信号标志
      atomic_store(&caller->signal_received_2, false);
      pthread_spin_unlock(&caller->caller_mutex_);
      printf("start remote thread for syscall no %d finished\n", caller->syscall_no_);
    }
}

/*void RemoteCaller_start_remote_thread(_Atomic(RemoteCaller *) caller) {

      if (!atomic_load(&caller->start_loop_)) {
      atomic_store(&caller->start_loop_, true);
      printf("start remote thread for syscall no %d\n", caller->syscall_no_);
      
      pthread_t td;
       int rc =
   pthread_create(&td, NULL, RemoteCaller_remote_call_thread_function, caller);
      if (rc != 0) {
            printf("Failed to create remote call thread for syscall no %d\n", caller->syscall_no_);
            return;
      }
      pthread_detach(td);

   
   while (!atomic_load(&caller->signal_received_2)) {
    pthread_cond_wait(&caller->caller_cond_, &caller->caller_mutex_);
    break;
}

// 重置信号标志
atomic_store(&caller->signal_received_2, false);


      printf("start remote thread for syscall no %d finished\n", caller->syscall_no_);
    }
}*/

void RemoteCaller_stop_remote_thread(RemoteCaller *caller) {
    caller->start_loop_ = false;
}

long RemoteCaller_remote_syscall1(_Atomic(RemoteCaller *) caller_atomic, struct sigcontext *sigctx) {
_Atomic(RemoteCaller *) caller = atomic_load(&caller_atomic);
    printf("locked exec remote_syscall\n");
    atomic_store(&caller->call_args_, sigctx);
    printf("wake up remote thread\n");

// 发送信号

atomic_store(&caller->signal_received_1, true);
pthread_cond_signal(&caller->callee_cond_);


    printf("wait remote thread...\n");

pthread_spin_lock(&caller->caller_mutex_);
/*atomic_init(&caller->signal_received_, false);*/
while (!atomic_load(&caller->signal_received_)) {
    pthread_cond_wait(&caller->caller_cond_, &caller->caller_mutex_);
    break;
}

// 重置信号标志
atomic_store(&caller->signal_received_, false);
pthread_spin_unlock(&caller->caller_mutex_);
// 读取 call_result_
unsigned long ret = atomic_load(&caller->call_result_);

// 写入 call_result_
atomic_store(&caller->call_result_, ret);
    printf("unlocked exec remote_syscall\n");
    return ret;
}

long RemoteCaller_remote_syscall(_Atomic(RemoteCaller *) caller_atomic, struct sigcontext *sigctx) {
_Atomic(RemoteCaller *) caller = atomic_load(&caller_atomic);
    printf("locked exec remote_syscall\n");
    atomic_store(&caller->call_args_, sigctx);
    printf("wake up remote thread\n");

// 发送信号

atomic_store(&caller->signal_received_1, true);
pthread_cond_signal(&caller->callee_cond_);


    printf("wait remote thread...\n");

pthread_spin_lock(&caller->caller_mutex_);
/*atomic_init(&caller->signal_received_, false);*/
while (!atomic_load(&caller->signal_received_)) {
    pthread_cond_wait(&caller->caller_cond_, &caller->caller_mutex_);
    break;
}

// 重置信号标志
atomic_store(&caller->signal_received_, false);
pthread_spin_unlock(&caller->caller_mutex_);
// 读取 call_result_
unsigned long ret = atomic_load(&caller->call_result_);

// 写入 call_result_
atomic_store(&caller->call_result_, ret);
    printf("unlocked exec remote_syscall\n");
    return ret;
}

#define SECMAGIC 0xdeadbeef

void sigsys_handler(int sig, siginfo_t *info, void *secret) {

      


    ucontext_t *ctx = (ucontext_t *) secret;
    struct sigcontext *sigctx = (struct sigcontext *) &ctx->uc_mcontext;
    bool is_handle_syscall = false;
#if defined(__aarch64__)
    is_handle_syscall = *(((uint32_t *) info->si_call_addr) - 1) == 0xd4000001; //01 00 00 d4svc   #0
    int sysno = sigctx->regs;
    unsigned long *presult = (unsigned long *) &sigctx->regs;
#else
    printf("unsupport arch\n");
//    exit(0);
#endif
    if (is_handle_syscall) {
   
      long ret = my_syscall(sysno,
                                       RemoteCaller_get_syscall_param(sigctx, 0),
                                       RemoteCaller_get_syscall_param(sigctx, 1),
                                       RemoteCaller_get_syscall_param(sigctx, 2),
                                       RemoteCaller_get_syscall_param(sigctx, 3),
                                       RemoteCaller_get_syscall_param(sigctx, 4),
                                       RemoteCaller_get_syscall_param(sigctx, 5),
                                       RemoteCaller_get_syscall_param(sigctx, 6),
                                       RemoteCaller_get_syscall_param(sigctx, 7)
                                       );;
      *presult = ret;
    }
}
void RemoteCaller_handleSigsys() {
      printf("register SIGSYS start\n");
      struct sigaction act;
      struct sigaction old_act;
      sigemptyset(&act.sa_mask);
      act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_SIGINFO;
      act.sa_sigaction = sigsys_handler;
      sigaction(SIGSYS, &act, &old_act);
      printf("register SIGSYS end\n");
}



int svc_register_hook1(int signo){
    struct sock_filter filter[] = {
      BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
                (offsetof(struct seccomp_data, nr))),
      BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, signo, 0, 1),
      BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),
      BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
    };
    struct sock_fprog prog = {
      .len = (unsigned short)(sizeof(filter)/sizeof(filter)),
      .filter = filter,
    };

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
      printf("prctl(NO_NEW_PRIVS)");
      goto failed;
    }
    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
      printf("prctl(SECCOMP)");
      goto failed;
    }
    return 0;

failed:
    if (errno == EINVAL)
      printf("SECCOMP_FILTER is not available. :(n\n");
    return -1;
}

int svc_register_hook(int signo){
    struct sock_filter filter[] = {
      BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
      BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, signo, 0, 2),
   /*   BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args)),
      BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECMAGIC, 0, 1),*/
      BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, instruction_pointer)),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (uint64_t)&my_syscall+0x20, 0, 1),
      BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
      BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP)
   
    };
    struct sock_fprog prog = {
      .len = (unsigned short)(sizeof(filter)/sizeof(filter)),
      .filter = filter,
    };

    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
      printf("prctl(NO_NEW_PRIVS)");
      goto failed;
    }
    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
      printf("prctl(SECCOMP)");
      goto failed;
    }
    return 0;

failed:
    if (errno == EINVAL)
      printf("SECCOMP_FILTER is not available. :(n\n");
    return -1;
}
int svc_hook(int sysno, void *before_hook_func, void *after_hook_func, void *patch_func){
// svc_register_hook(sysno);
/*    RemoteCaller_registerSyscall(sysno, before_hook_func, after_hook_func, patch_func);*/
    RemoteCaller_handleSigsys();
   return svc_register_hook(sysno);
}

AO1199 发表于 5 天前

慢慢学习中!
页: [1]
查看完整版本: svc hook框架