如果一个木马要隐藏起来,不被系统管理员发现。截获系统调用似乎是必须的。大部分情况下,通过修改系统调用表来实现系统调用的劫持。下面是一个典型的截获系统调用的模块:
模块一:
用这种方法实现系统调用有个前提,就是系统必须导出sys_call_table内核符号,但是在2.6内核和有些2.4内核的系统(比如redhat as 3)中,sys_call_table不再导出。也就是说模块中不能再通过简单的extern void *sys_call_table[];来获得系统调用表地址。所幸的是,即使内核不导出sys_call_table,也可以在内存中找到它的地址,下面是它的实现方法:
模块二:(2.4和2.6内核测试通过)
getscTable()是在内存中查找sys_call_table地址的函数。
每一个系统调用都是通过int 0x80中断进入核心,中断描述符表把中断服务程序和中断向量对应起来。对于系统调用来说,操作系统会调用system_call中断服务程序。system_call函数在系统调用表中根据系统调用号找到并调用相应的系统调用服务例程。idtr寄存器指向中断描述符表的起始地址,用__asm__ ("sidt %0" : "=m" (idtr));指令得到中断描述符表起始地址,从这条指令中得到的指针可以获得int 0x80中断服描述符所在位置,然后计算出system_call函数的地址。反编译一下system_call函数可以看到在system_call函数内,是用call sys_call_table指令来调用系统调用函数的。
因此,只要找到system_call里的call sys_call_table(,eax,4)指令的机器指令就可以获得系统调用表的入口地址了。
对于截获文件系统相关的系统调用,Adore-ng rootkit提供了一种新的方法。简单的说,就是通过修改vfs文件系统的函数跳转表来截获系统调用,这种方法不用借助于系统调用表。
下面是它的实现方法:
模块三:(2.4和2.6内核测试通过)
-------------------------------------------------------------------------------------------------------------------------------------------
下面补充下x64的系统调用劫持。
和x86相比,x64的系统调用劫持有以下变化:
1、搜索的字符串不同:x64需要搜索的字符串是"/xff/x14/xc5";
2、cr0寄存器是64位的,在打开、关闭页面读写权限时,要使用64位的掩码,高32为全是f
3、在获得sys_call_table地址时需要和0xffffffff00000000相或。否则可能宕机。