Rootkit技术的主要原理

  rootkit 的主要分类:应用级 -> 内核级 -> 硬件级
  早期的 rootkit 主要为应用级 rootkit ,应用级 rootkit 主要通过替换 login ps ls netstat 等系统工具,或修改 .rhosts 等系统配置文件等实现隐藏及后门;硬件级 rootkit 主要指 bios rootkit ,可以在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权,也可以采用虚拟机技术,使整个操作系统运行在 rootkit 掌握之中;目前最常见的 rootkit 是内核级 rootkit
  内核级 rootkit 又可分为 lkm rootkit 、非 lkm rootkit lkm rootkit 主要基于 lkm 技术,通过系统提供的接口加载到内核空间,成为内核的一部分,进而通过 hook 系统调用等技术实现隐藏、后门功能。非 lkm rootkit 主要是指在系统不支持 lkm 机制时修改内核的一种方法,主要通过 /dev/mem /dev/kmem 设备直接操作内存,从而对内核进行修改。
  非 lkm rootkit 要实现对内核的修改,首先需要获得内核空间的内存,因此需要调用 kmalloc 分配内存,而 kmalloc 是内核空间的调用,无法在用户空间直接调用该函数,因此想到了通过 int 0x80 调用该函数的方法。先选择一个不常见的系统调用号,在 sys_call_table 中找到该项,通过写 /dev/mem 直接将其修改为 kmalloc 函数的地址,这样当我们在用户空间调用该系统调用时,就能通过 int 0x80 进入内核空间,执行 kmalloc 函数分配内存,并将分配好的内存地址由 eax 寄存器返回,从而我们得到了一块属于内核地址空间的内存,接着将要 hack 的函数写入该内存,并再次修改系统调用表,就能实现 hook 系统调用的功能。
Rootkit的常见功能:
  隐藏文件:通过 strace ls 可以发现 ls 命令其实是通过 sys_getdents64 获得文件目录的,因此可以通过修改 sys_getdents64 系统调用或者更底层的 readdir 实现隐藏文件及目录,还有对 ext2 文件系统直接进行修改的方法,不过实现起来不够方便,也有一些具体的限制。
  隐藏进程:隐藏进程的方法和隐藏文件类似, ps 命令是通过读取 /proc 文件系统下的进程目录获得进程信息的,只要能够隐藏 /proc 文件系统下的进程目录就可以达到隐藏进程的效果,即 hook sys_getdents64 readdir 等。
  隐藏连接: netstat 命令是通过读取 /proc 文件系统下的 net/tcp net/udp 文件获得当前连接信息,因此可以通过 hook sys_read 调用实现隐藏连接,也可以修改 tcp4_seq_show udp4_seq_show 等函数实现。
  隐藏模块: lsmod 命令主要是通过 sys_query_module 系统调用获得模块信息,可以通过 hook sys_query_module 系统调用隐藏模块,也可以通过将模块从内核模块链表中摘除从而达到隐藏效果。
  嗅探工具:嗅探工具可以通过 libpcap 库直接访问链路层,截获数据包,也可以通过 linux netfilter 框架在 IP 层的 hook 点上截获数据包。嗅探器要获得网络上的其他数据包需要将网卡设置为混杂模式,这是通过 ioctl 系统调用的 SIOCSIFFLAGS 命令实现的,查看网卡的当前模式是通过 SIOCGIFFLAGS 命令,因此可以通过 hook sys_ioctl 隐藏网卡的混杂模式。
  密码记录:密码记录可以通过 hook sys_read 系统调用实现,比如通过判断当前运行的进程名或者当前终端是否关闭回显,可以获取用户的输入密码。 hook sys_read 还可以实现 login 后门等其它功能。
日志擦除:传统的 unix 日志主要在 /var/log/messages /var/log/lastlog /var/run/utmp /var /log/wtmp 下,可以通过编写相应的工具对日志文件进行修改,还可以将 HISTFILE 等环境变设为 /dev/null 隐藏用户的一些操作信息。
内核后门:可以是本地的提权后门和网络的监听后门,本地的提权可以通过对内核模块发送定制命令实现,网络内核后门可以在 IP 层对进入主机的数据包进行监听,发现匹配的指定数据包后立刻启动回连进程。
Rootkit的主要技术:
   lkm 注射、模块摘除、拦截中断( 0x80 0x01 )、劫持系统调用、运行时补丁、 inline hook 、端口反弹……
   lkm 注射:也是一种隐藏内核模块的方法,通过感染系统的 lkm ,在不影响原有功能的情况下将 rootkit 模块链接到系统 lkm 中,在模块运行时获得控制权,初始化后调用系统 lkm 的初始化函数, lkm 注射涉及到 elf 文件格式与模块加载机制。
  模块摘除:主要是指将模块从模块链表中摘除从而隐藏模块的方法,最新加载的模块总是在模块链表的表头,因此可以在加载完 rootkit 模块后再加载一个清除模块将 rootkit 模块信息从链表中删除,再退出清除模块,新版本内核中也可以通过判断模块信息后直接 list_del
  拦截中断:主要通过 sidt 指令获得中断调用表的地址,进而获取中断处理程序的入口地址,修改对应的中断处理程序,如 int 0x80 int 0x1 等。其中拦截 int 0x1 是较新的技术,主要利用系统的调试机制,通过设置 DR 寄存器在要拦截的内存地址上下断点,从而在执行到指定指令时转入 0x1 中断的处理程序,通过修改 0x1 中断的处理程序即可实现想要的功能。
  劫持系统调用:和拦截中断类似,但主要是对系统调用表进行修改,可以直接替换原系统调用表,也可以修改系统调用表的入口地址。在 2.4 内核之前,内核的系统调用表地址是导出的,因此可以直接对其进行修改。但在 2.6 内核之后,系统调用表的地址已经不再导出,需要对 0x80 中断处理程序进行分析从而获取系统调用表的地址。
  运行时补丁:字符设备驱动程序和块设备驱动程序在加载时都会向系统注册一个 Struct file_operations 结构实现指定的 read write 等操作,文件系统也是如此,通过修改文件系统的 file_operations 结构,可以实现新的 read write 操作等。
   inline hook :主要是指对内存中的内核函数直接修改,而不影响原先的功能,可以采用跳转的办法,也可以修改对下层函数的 call offset 实现。

  端口反弹:主要是为了更好的突破防火墙的限制,可以在客户端上监听80端口,而在服务器端通过对客户端的80端口进行回连,伪装成一个访问web服务的正常进程从而突破防火墙的限制。

你可能感兴趣的:(Rootkit技术的主要原理)