adore rootkit分析1.简介 通常LKM用来为系统提供额外的功能,而不用重新编译内核,例如:加载设备驱动程序和其它的硬件驱动程序等。Linux、Solaris和BSD(Free、Net和open)等操作系统都使可加载内核模块实现系统的某些功能。某些rootkit能够利用这种机制,把自己作为内核的可加载模块运行,在内核层欺骗应用程序,而不用修改应用程序本身,因此比传统的rootkit具有更好的隐蔽性。现在LKM rootkit已经有好多种了,例如:slkm、knark和adore。本文对adore rootkit进行分析(注意:adore rootkit不是adore 蠕虫)。 adore是一个Linux LKM(Loadable Kernel Module)rootkit。作者是Stealth。可以用于Linux-2.2.x和Linux-2.4.x系列的内核。其核心部分就是一个叫做adore.o的LKM。除此之外,还有一个用于隐藏adore.o的模块cleaner.o,一个控制工具ava,以及一个启动脚本startadore。 adore的源代码包括以下文件: ChangelogLICENSE Makefile.gen <--如果configure脚本执行失败,可以使用这个文件 README TODO adore.c <--adore.o模块的源代码 adore.h ava.c <--控制命令 cleaner.c <--cleaner.o模块的源代码,用于隐藏adore模块 configure <--安装脚本 dummy.c libinvisible.c <--libinvisible是ava和adore模块之间的接口 libinvisible.h rename.c startadore <--启动脚本 2.adore模块 前面我们讲过,adore rootkit的核心部分是adore.o模块。在这个模块中,通过伪造一些系统调用,实现了进程的隐藏/重现、目录的隐藏/重现、控制进程(ava)的验证以及后门的隐藏等功能。这个模块中的函数大体可以分为:
adore rootkit使用如下函数替代真正的系统调用:n_getdents、n_getdents64、n_fork、n_clone、n_kill、n_write、n_close、n_mkdir、n_oldstat、n_oldlstat、n_stat、n_lstat、n_stat64、n_lstat64、n_open。这些函数基本都是真正的相关系统调用封装。 执行adore模块的初始化(使用伪造的系统调用替代原来的系统调用)和卸载模块的清理工作(恢复原始的系统调用等)。 包括:hide_process、remove_process、unhide_process、strip_invisible、unstrip_invisible。这些函数通过修改指定进程的进程控制块(task_struct)中的某些信息,实现进程的隐藏、删除和重现功能。 包括函数:my_atoi、my_find_task、is_invisible、is_secret、is_secret64、fp_put、fp_get 和宏:REPLALE、RESTORE。 2.1.adore模块的初始化和卸载函数 adore的初始化函数init_module int init_module(void){ struct task_struct *p = current;/*当前进程*/ lock_kernel(); EXPORT_NO_SYMBOLS;/*没有其它模块需要的符号,不向模块符号表导出符号*/ for (; p->pid != 1; p = p->next_task)/*寻找init(1号)进程*/ ; init_hook = p; /*保存init进程的位置,用来指定for_each_task(adore.h)宏进行搜索的位置*/ . . . REPLACE(write); REPLACE(getdents); /*修改内核的系统调用表(sys_call_table)使用伪造的系统调用替代真正的系统调用*/ /*而真正的系统调用被以o_系统调用名的方式重新命名(如:o_write)*/ . . . } cleanup_module函数 这个函数在adore模块被卸载时,使用RESTORE宏重新恢复真正的系统调用。 2.2.木马函数 2.2.1.hide_process/unhide_process/remove_process 这三个函数用来隐藏(hide_process)以及重现(unhide_process)/删除(remove_process)进程。adore在Linux的进程控制块(task_struct,在include/linux/sched.h文件中定义)的进程标志域(task_struct.flags))引入了两个进程标志:PF_INVISIBLE和PF_AUTH。如果进程控制块标志域的PF_INVISIBLE位被置位就表示进程是不可以显示的。进程标志PF_AUTH是用来限制对于隐藏进程的操作,只能具有PF_AUTH进程标志的进程才具有对被隐藏进程某些操作权限(例如:kill),而如果不进行验证,用户只要向系统的第2到第NR_TASKS号进程发出SIGVISIBLE信号,就可以轻松使被adore隐藏的进程露出原型。 BTW,进程的验证是由伪造的系统变量mkdir完成的,具体验证过程将在ava节中详细解释。 当用户执行有关进程的系统调用时,伪造的系统调用就会检查相关进程的进程控制块标志域的这两个标志是否已经设置,从而判断是否执行针对这个进程的操作。下面我们看一下这两个函数的源代码
int hide_process(pid_t pid) { struct task_struct *p; if (pid <= 1) return -1; /*进制对idle(0)进程和init(1)进程进行任何的操作*/ if ((p = my_find_task(pid)) == NULL) return -1; p->flags |= (PF_INVISIBLE|PF_AUTH); /*把进程标志为隐藏的,并且使这个进程也具有对隐藏进程进行操作的权限*/ return 0; } { struct task_struct *p = my_find_task(pid); if (!p) return -1; p->flags &= ~(PF_INVISIBLE|PF_AUTH); /*把进程控制块的PF_INVISIBLE和PF_AUTH标志清除*/ return 0; } int remove_process(pid_t pid) { struct task_struct *p; if (pid <= 1) return -1; /*不允许删除IDLE和init进程*/ . . . if (p->p_cptr != NULL) 上一篇:HA解决方案 下一篇:OpenLDAP快速指南 更多相关文章
|
推荐文章
精彩文章
|