如何通过钩子sys_exit_group和sys_kill使进程无法退出
How to make a process unable to exit by hook sys_exit_group and sys_kill
我正在使用 Android 8.1 Pixel2 XL phone。
我已经挂钩 sys_call_table 并使用内核模块用我自己的函数替换了系统调用。
我想让一个应用程序无法退出。
我正在尝试使应用程序的 sys_exit_group 和 sys_kill 无效。
我自己的职能该怎么做。
我想调试一个应用程序,但是它打开了反调试。所以我想挂钩系统调用
我试过直接 return,但没用。这次系统会调用 sys_kill again.But,我无法从它的 pid 中获取应用程序的 uid。
asmlinkage long my_sys_kill(pid_t pid, int sig)
{
char buff[MAX_PATH] = {0};
kuid_t uid = current->cred->uid;
int target_uid = get_uid_from_pid(pid);
if (target_uid == targetuid)
{
printk(KERN_DEBUG "@Tsingxing: kill hooked uid is %d pid is %d, tragetuid is %d, packagename: %s\n",uid.val,pid, target_uid, buff);
return 0;
}
printk(KERN_DEBUG "@Tsingxing:kill called uid is %d,pid is %d, traget_uid is %d\n",uid.val,pid,target_uid);
return origin_sys_kill(pid, sig);
}
asmlinkage long my_sys_exit_group(int error_code)
{
char buff[MAX_PATH] = {0};
kuid_t uid = current->cred->uid;
long tgid = current -> tgid;
long pid = current->pid;
int target_uid = get_uid_from_pid(pid);
if (uid.val == targetuid || target_uid == targetuid)
{
printk(KERN_DEBUG "@Tsingxing:exit group hooked, pid is %ld\n",pid);
return 0;
}
return origin_sys_exit_group(error_code);
}
在非常高的水平上,这个行不通。当应用程序调用 _Exit
(exit
末尾的 possibly/likely)时,它没有指向任何进一步代码的路径 运行。这些函数通常甚至被标记为 _Noreturn
,这意味着编译器不会将 registers/calling 堆栈帧留在可以恢复执行的有意义的状态。即使这样做了,源代码级别的程序本身也不准备继续执行。
如果函数以某种方式返回,下一步将是运行远离错误代码执行,可能导致任意代码执行 如果应用程序一直在处理任何类型的不受信任的输入,则在攻击者的控制下。
实际上,exit
和 _Exit
函数的 libc 端实现可能会针对内核 bugs 进行强化(是的,你所要求的是一个错误),因此 SYS_exit_group
无法退出。我最近没有验证其他实现,但我知道我的 musl 会这样做,因为它很便宜,而且替代方案非常危险。
我已经解决了这个问题。我混合了 sys_call_table 和 compat_sys_call_table。 Target 应用程序使用的是 compat_sys_call_table,但我使用的是 __NR_xxx。我使用 __NR_compat_xxx 方法解决了这个问题。只需 return 直接进入 compat_sys_call_exit_group.
我正在使用 Android 8.1 Pixel2 XL phone。 我已经挂钩 sys_call_table 并使用内核模块用我自己的函数替换了系统调用。 我想让一个应用程序无法退出。 我正在尝试使应用程序的 sys_exit_group 和 sys_kill 无效。 我自己的职能该怎么做。
我想调试一个应用程序,但是它打开了反调试。所以我想挂钩系统调用
我试过直接 return,但没用。这次系统会调用 sys_kill again.But,我无法从它的 pid 中获取应用程序的 uid。
asmlinkage long my_sys_kill(pid_t pid, int sig)
{
char buff[MAX_PATH] = {0};
kuid_t uid = current->cred->uid;
int target_uid = get_uid_from_pid(pid);
if (target_uid == targetuid)
{
printk(KERN_DEBUG "@Tsingxing: kill hooked uid is %d pid is %d, tragetuid is %d, packagename: %s\n",uid.val,pid, target_uid, buff);
return 0;
}
printk(KERN_DEBUG "@Tsingxing:kill called uid is %d,pid is %d, traget_uid is %d\n",uid.val,pid,target_uid);
return origin_sys_kill(pid, sig);
}
asmlinkage long my_sys_exit_group(int error_code)
{
char buff[MAX_PATH] = {0};
kuid_t uid = current->cred->uid;
long tgid = current -> tgid;
long pid = current->pid;
int target_uid = get_uid_from_pid(pid);
if (uid.val == targetuid || target_uid == targetuid)
{
printk(KERN_DEBUG "@Tsingxing:exit group hooked, pid is %ld\n",pid);
return 0;
}
return origin_sys_exit_group(error_code);
}
在非常高的水平上,这个行不通。当应用程序调用 _Exit
(exit
末尾的 possibly/likely)时,它没有指向任何进一步代码的路径 运行。这些函数通常甚至被标记为 _Noreturn
,这意味着编译器不会将 registers/calling 堆栈帧留在可以恢复执行的有意义的状态。即使这样做了,源代码级别的程序本身也不准备继续执行。
如果函数以某种方式返回,下一步将是运行远离错误代码执行,可能导致任意代码执行 如果应用程序一直在处理任何类型的不受信任的输入,则在攻击者的控制下。
实际上,exit
和 _Exit
函数的 libc 端实现可能会针对内核 bugs 进行强化(是的,你所要求的是一个错误),因此 SYS_exit_group
无法退出。我最近没有验证其他实现,但我知道我的 musl 会这样做,因为它很便宜,而且替代方案非常危险。
我已经解决了这个问题。我混合了 sys_call_table 和 compat_sys_call_table。 Target 应用程序使用的是 compat_sys_call_table,但我使用的是 __NR_xxx。我使用 __NR_compat_xxx 方法解决了这个问题。只需 return 直接进入 compat_sys_call_exit_group.