目前是一个杀毒软件急需大革命的时代,网络上的病毒、木马、蠕虫、恶意软件不断肆虐,尤其是各种木马、后门软件已经成灾。虽然传统的杀毒软件还在奋力抵挡病毒的人侵,但这种带有滞后性的杀毒思想已经难以满足用户安全的要求。
很多未知的病毒,甚至ODay攻击经常出现,导致传统的杀毒手段很被动。从原理上讲,病毒特征码的杀毒方法是不能抵御这些未知病毒和D a y的,因为这些写未知病毒和ODay的人在暗处.而杀毒软件在明处。把这些未知病毒和ODay攻击放出来前,当然是通过大量测试的,命中率是相当高的.逃过常用杀毒软件的”法眼”是这些病毒的重要指标。病毒的变形技术、免杀技术给传统的杀毒软件带来了很大的压力。
在这样的局面下.涌现出了很多基于行为特征来杀毒的杀毒软件,还有一些主动防御杀毒软件,稍微使得病毒肆虐的局面有些好转。因此.笔者认为通过程序行为来查毒、杀毒的理念应该是今后安全领域研究的热点和重点。因此我的硕士毕业题目也选定了这样一个方向.研究基于行为特征的攻防技术。那么完整地、准确地得到任何一个程序在任何一个时刻的行为是我迈出的第一步,这应该说是最基础的.否则,任何后续的算法都是徒劳的。经过近一个月的时间,从零开始,学习驱动,解读sysinternal诸多软件,不断遇到问题、遇到困难,不断地做实验,不断地解决问题,终于打造出了自己的程序行为监视器1.0版-BehaviorMon 1.O。本文将我在这个过程中遇到的问题,使用的主要技术、代码详细整理出来,供读者参考。
基于行为特征的杀毒逻辑
上面已经提到,基于行为特征来杀毒已经不同于传统的杀毒思想.它是化病毒文件特征码为行为特征。可能有的朋友会认为行为特征最后也会和文件特征码一样,带有先天的滞后性.而且误杀率会很高。这个问题在网上争论很激烈.一直没有统一的观点,仁者见仁、智者见智。我不否认确实有些问题的存在。但事实上,仔细想想很多病毒.甚至是未知病毒,在行为方面都有很多相似或相同之处.这样一来,借助行为特征杀毒从原理上就可以很好地抵御未知病毒,并且同样一条特征.也许能够查杀更多的病毒。于是变形技术将被淘汰.与之来的将是绕过技术的威胁,这就是目前涌现了很多针对主动防御软件的各种绕过技术出现的原因。这一点也说明了行为毒确实有一定程度的滞后性。不过绕过无非也是种行为,提取其行为特征即可。与病毒文件的变形相比,绕过能有那么大的变化空间吗7这样就可以一步步将病毒逼向绝路。总的来说。我觉得行为杀毒一定会很有前景。关于行为特征的杀毒逻辑,仔细想想,其实很简单。我设计了一种基于行为特征的杀毒逻辑,如图1所示,虽然不知道杀毒软件公司是怎么做的,不过估计原理思想应该差不多吧。
本系统分为4大模块程序行为提取模块、恶意行为特征库模块、规则匹配模块和恶意行为回滚/恢复模块。各个模块的介绍如下。
程序行为提取模块 通过SSDT HOOK的方式,编写一个卜lative API拦截的驱动程序,能够实时地知道任何一个程序,在任何一个时刻调用了什么原生AP函数,进而以此作为一个行为。在一段时间内该程序调用的这些函数组成的序列就作为这个程序的行为或行为序列。该模块的主要作用就在于高效的、稳定的工作于Ring0上.从而提取所有程序的行为。恶意行为特征库模块——该模块主要作用在于通过大量的恶意程序、病毒、木马来训练并构建一个合理的恶意行为特征知识库,有了这个库就可以形成一些规则,只要一个程序的行为和某条规则匹配,就认定该程序是某种恶意程序。规则匹配模块——该模块用于在模块1实时地得到一个程序的动态行为序列后,高效准确地和上述的行为特征规则库匹配出是否是恶意程序。
恶意行为回滚/恢复模块——该模块用于在检测出某个程序是恶意程序后,将其在检测之前所作的恶意行为进行回滚,或恢复对操作系统的各项更改。当然,本文仅介绍程序行为提取部分内容.其他模块还在实现中,在后续的研究过程中还会和读者继续交流。
程序行为监视器(BehaviorMon)的实现BehaviorWion由两部分组成一是后台驱动程序BeHaviorMon.sys二是前台应用程序BehaviorMon.exa。这里先把前台程序界面展示一下。如图2所示。在前台程序界面中蓝色显示的是注册表操作行为,紫色显示的是文件操作行为,红色显示的是内存操作行为,黑色显示的是其他操作行为。其实应该还有网络操作行为,但目前还未实现,将在下一个版本中完善。
另外,本程序主要参考了sysinternal公司的RegMon和FileMon,因此界面上有很多相似之处。同时在功能方面有所加强。例如前台能够控制后台驱动动态的hook哪些N ative API.也可以动态的unHook;可以针对一个特定的程序进行行为监视。前台程序运行起来后.要做的第一件事就是安装我们的驱动程序,并由驱动程序内部来创建一个虚拟设备(“\\Device\\Behavior Mon")。这里安装驱动是通过服务来安装的,注意在创建服务beHaviormonservice时要声明服务类型为内核驱动类型。具体看下面的代码和注释吧。
驱动加载到内核空间后,开始执行入口函数DriverEntry。该函数相当于C语言的main函数,它在驱动程序被加载进内存的时候调甩。该函数中第一个任务就是要创建设备和创建符号链接,第二个任务就是要设定驱动程序对象的几个函数指针。
有了”\\DosDevices\\BEHAVIORMON"这个设备符号连接后,我们就可以在前台使用CreateFile函数来访问我们的虚拟设备“\\Device\\BehaviorMon"了。下面是前台访问该设备,并通过DevicaloControl函数控制驱动来HookNative API函数的代码。
注意上面向驱动输入的是native API函数在SSDT表中的服务序号,即Service index。关于上面为什么要“+1“,大家可以到网上搜索看看关于SSDT hook相关的文章。进入驱动的派遣例程函数后,对控制号IOCTL_BEHAVIORM OKI_HOOK进行处理,实现hook的具体代码如下。
hook了Native APi函数后,剩下的就是前台和后台驱动程序的通信,来获取拦截到的程序行为数据,然后在前台界面中的列表控件中显示出来。这部分前台应用程序和后台驱动程序通信的内容已经在我写的《深入分RegMon的编程实现》文中有详细的介绍,这里不再赘述。关键问题与解决方法以上讲解了如何步步安装驱动到实现SSDThook,但要实现行为监视,光拦截到Native API函数的调用行为还不够,还应该分析调用时传入的参数,得到有效信息。例如我们拦截到了一个程序调用了ntOpenKey.但不知道Open的是哪个Key.那有什么用.必须知道Open的是哪个Key才算截获了一个注册表操作行为。不仅是注册表,还有文件、内存操作,等等。在实现对Native API函数参数解析,得到有效信息的过程中我遇到了如下的一些问题。
1、在驱动中获得调用Native API函数的进程对应PE文件的完整路径
上面这个函数想必大家都不陌生,利用它在Windows XP/2000的驱动中可以得到当前进程的全路径。然而我在测试的时候发现,有些情况会出错,导致虚拟机直接蓝屏,让我想不通为什么。上面加粗的代码,是最终得到ImageFile这个Unicode字符串地址的代码。在这之前的一步.dwAddress-般情况下就是Ox20000.而执行完加粗代码后,dwAddress大概就是Ox2yyyy的样子,反正比Ox20000要大。然而有些时候,执行完加粗代码后.得到的好像不是Ox2yyyy,而是Oxyyyy.这样就没有得到mageFile的地址,而是Ox20000的偏移量。虽然我没有想清楚为什么Windows会这样搞.但这里可以对上面的函数做点修改,暂时得到正确的函数体来得到正确的ImageFile的地址,我修改的函数如下。
经过我的修改后,无论在虚拟机中还是真实系统中,再也没有出现过蓝屏。这样修改也是比较保险的,至少不会在驱动中发生内存访问错误,否则就惨了!
2、从FileHandle到文件完整路径的方法
在NtWriteFile、ntRestoreKey等函数中,经常需要通过文件句柄FileHancile获得该文件的完整路径,我把我的几种方法整理如下。由于篇幅原因,函数内部实现请参见本文的程序源码(驱动部分)。
总结
希望通过本文及源码能对大家有所帮助。事实上,驱动程序涉及的内容相当丰富,深入到了操作系统底层的每个角落。通过学习驱动程序编写,实践动手自己写这样一个BehaviorMon.能够真切的感受到自己的知之甚少,总是感到还有很多很多需要学习、需要研究,时间总是那么少.而问题总是那么多!