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);
}
慢慢学习中!
页:
[1]