本文为看雪论坛优秀文章
看雪论坛作者ID:xxxlion
1. 给libc添加个导出符号(可不做)
直接在linux内核里添加了调用,直接syscall(_NR_ID)内核,是可以实现自定义syscall的,主要是这里也了解到了就顺手记下。
在unistd.h中添加syscall id,跟着别的写就行了,sys_antidebug_update是linux内核自定义函数,下面会提到。
比如我在这里加了__antidebug_update函数,将会调用linux内核里的antidebug_update函数,在arm64架构下的。
return_type func_name[|alias_list]:syscall_name[:socketcall_id] arch_list
int __antidebug_update:antidebug_update(pid_t) arm64
int getrusage(int, struct rusage*) all
int __getpriority:getpriority(int, id_t) all
然后添加libc的导出符号,在这个路径下,编译即可直接调用libc的函数实现封装好的syscall。
bionic工具生成的map文件在这里能看到:
踩坑1
踩坑2
后面再user层就可以先用extern c 声明下 aadebug,然后直接调用了。
2. 在linux内核里添加syscall
调用syscall会产生中断,在arm64的汇编是svc,中断产生异常后,进入svc handler。
在kernelxiaomism8250archarm64kernelsyscall.c下,我复制一段关键代码。
asmlinkage void el0_svc_handler(struct pt_regs *regs)
{
sve_user_discard();
el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table);
}
static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
const syscall_fn_t syscall_table[])
{
unsigned long flags = current_thread_info()->flags;
regs->orig_x0 = regs->regs[0];
regs->syscallno = scno;
...
invoke_syscall(regs, scno, sc_nr, syscall_table);
...
}
static long __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
{
return syscall_fn(regs);
}
static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
unsigned int sc_nr,
const syscall_fn_t syscall_table[])
{
long ret;
if (scno < sc_nr) {
syscall_fn_t syscall_fn;
syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];
ret = __invoke_syscall(regs, syscall_fn);
} else {
ret = do_ni_syscall(regs, scno);
}
regs->regs[0] = ret;
}
syscall_table[scno](regs);
用 aarch64-linux-gnu-gcc 编译(ubuntu 可以直接apt装arm的交叉编译工具),不要忘记-static选项,刷机到手机上运行下,可以看到函数逻辑是走了的。
但我就是看不到printk打的日志去哪了,打算封装个函数把日志写到文件去了。unistd.h到处都是,看得人晕。
看雪ID:xxxlion
https://bbs.kanxue.com/user-home-792494.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
原文始发于微信公众号(看雪学苑):【从源码过反调试】给安卓12内核增加个syscall