李伟光 黄常全
四川理工学院 四川 643000
在互联网日益发达的今天,计算机病毒日益猖獗,数量呈几何数据增长,面对如此庞大数量的病毒,如何快速准确的识别病毒、如何智能识别未知病毒是反计算机病毒的关键技术。
目前的计算机操作系统普遍采取了分层结构设计,应用程序只能通过操作系统的API接口才能访问计算机资源。比如说 Windows操作系统上的病毒程序如果想要感染别的文件,不可避免的要使用API函数CreateFile、WriteFile这类API函数。一般来说执行程序文件几乎是不需要修改的,显然一个程序修改另一个可执行程序的内容是一种值得警惕的危险操作。目前Windows仅仅对自己的系统文件(Windows下的exe和dll文件)有保护,一旦对系统文件进行修改,则会弹出警告对话框提示操作用户。所以监视程序调用了哪些API函数是判断程序功能和动作的一个特征。
以下列举一些病毒常用的危险函数以及这些函数在病毒中的作用,如果发现有程序调用这些函数,则需要注意。
API指令 解释CreateFile /WriteFile打开/写文件。如果发现对可执行文件进行修改,需要重点注意。VirtualAllocEx分配内存函数。一般程序只会为自己分配内存。如果发现有程序对别的进程进行内存分配,则需要注意。ReadProcessMemory/WriteProcessMemory读写内存函数,一般程序应该对自己进程内空间进行读写。如果发现对其他进程空间进行读写,则需要注意。VirtualProtect/ VirtualProtectEx改变内存读写属性函数。一般程序代码段为只读属性。如果发现有程序试图修改代码的只读属性为读写属性,则需要注意。SetWindowsHook/SetWindowsHookEx钩子函数。通过该函数可以入侵其他程序,需要关注调用此函数的程序。CreateRemoteThread创建线程函数。该函数可以入侵进另一个进程为另一个进程创建一个线程。需要注意。… …
一个程序需要调用的API函数都在PE文件的输入表中,对PE文件的输入表进行扫描,就可以基本确定该程序大致需要调用哪些API函数。
Windows平台下的可执行文件是按照PE(Portable Excute)文件格式来组织的。正常的程序一般在编译程序下会被将程序中不同的数据按照PE文件格式组织在一起。PE文件的真正内容划分成块,称之为sections(节)。每节是一块拥有共同属性的数据,比如代码/数据、读/写等。我们可以把PE文件想象成一逻辑磁盘,PE header 是磁盘的boot扇区,而sections就是各种文件,每种文件自然就有不同属性如只读、系统、隐藏、文档等等。节的划分是基于各组数据的共同属性,而不是逻辑概念。重要的不是数据/代码是如何使用的,如果PE文件中的数据/代码拥有相同属性,它们就能被归入同一节中。不必关心节中类似于“data”,“code”或其他的逻辑概念,如果数据和代码拥有相同属性,它们就可以被归入同一个节中。下面是常见的节名及作用:
DOS MZ Header DOS stub PE header Section table Section 1 Section 2 Section ...Section n
其中常见的section节的名字和作用如下:
节名 作用.bss 未经初始化的数据.data 已经初始化的数据.rdata 只读的初始化数据.reloc 重定位表信息.rsrc 资源.text .exe或.dll文件的可执行代码
病毒程序与正常程序从PE文件格式比较来看有以下的一些特点:
(1)病毒程序为了更方便的隐藏和传播,一般都有尺寸的限制。而编译链接程序默认段大小为一页(4096字节)的整数倍,不足一页的自动将不足部分填充为0凑成一页,即每个section的尺寸都应该为页面的整数倍。一般正常程序至少都有4个段,则理论上浪费的空间有4*4096*50%=8K。而病毒程序为了控制病毒程序大小,将不同段都合并为一个段,经常将数据段、代码段等合并为一个段,减少了每个段都要对齐整数倍页而造成的尺寸浪费。并且将编译器默认的4096整页对齐更改为8字节或者16字节对齐,以达到最大限度的压缩尺寸的目的。
(2)病毒程序进入正常程序后,一般都需要做自修改或者变形,并修改宿主程序的代码段的代码,而且将数据段和代码段合并后,数据段是应该能读写修改的,其段属性应该为可读写执行。正常程序编译出来的代码段应具有只读属性的,而病毒程序需要将代码段的属性置为读写属性。
以VC程序为例,病毒程序一般都会修改编译选项达到以上目的:
#pragma comment(linker, "/merge:.rdata=.data") //只读属性初始化数据段合并进数据段
#pragma comment(linker, "/merge:.text=.data") //代码段合并进数据段
#pragma comment(linker, "/merge:.reloc=.data") //重定位段合并进数据段
#pragma comment(linker, "/SECTION:.data, RWE") //数据段设置为可读可写壳执行
如果发现一个程序只有一两个段且代码段,且应该属于只读属性的代码段具有了读写执行的属性就应当值得警惕。
病毒程序入侵其他程序具有和正常程序不同的操作特征。简单举例如下,我们知道一个可执行文件被操作系统装载的时候,操作系统会将操作系统的资源提供给程序,比如操作系统会加载执行程序需要的动态库进入内存并将动态库中的API的正确地址修改到被加载程序当中,会根据执行程序加载地址的不同而修改重定位代码和数据。而病毒代码入侵其他程序后,并没有经过操作系统装载器的加载,必须自己完成这些动作。为了完成这些动作,病毒首先得知道自己的装载地址。操作系统对指令指针寄存器EIP进行了保护,应用程序包括病毒无法直接访问该寄存器。然而病毒利用call指令会将函数返回地址压入堆栈的特点来获得自己在内存所在位置。特征指令如下:
指令 解释 OPCODE特征Call $+5 Pop ebp call $+5:把下一条指令当作函数调用,执行后,堆栈顶部就是返回地址,就是 pop ebp指令的地址。E8 00 00 00 00
类似特征还有:在内存中搜索kernel32.dll的地址、通过FS寄存器访问kernel32.dll的地址、加载ntdll.dll、user32.dll动态库。
病毒程序为了造成危害就具有一些有危害的操作。比如说一个木马程序的典型行为特征会想办法秘密运行,秘密连接internet网,下载恶意程序执行;调用具有入侵作用的api函数;病毒程序的自我复制和繁殖;为了自动启动修改操作系统的自动启动项目等等。下表列举了一些病毒常用的行为特征。
行为 目的和作用设置系统文件的隐藏属性。 病毒为了隐藏病毒文件。修改系统开机启动选项。 为了使病毒在开机后得到控制权。读写注册表敏感位置。对 windows的注册表敏感位置(自动启动选项、自动服务加载选项、远程访问控制选项等)进行读写。大规模的遍历访问计算机的其他文件。病毒为了感染其他文件,需要对计算机的其他文件进行大量的遍历访问,以找到需要感染的文件。打开敏感服务。 病毒为了在计算机开”后门”,秘密的打开计算机的远程访问服务。
续表
病毒程序虽然千变万化,变种繁多,但是病毒程序的功能、作用和目的还是大体差不多的,使用技术手段也万变不离其中,我们可以对这些病毒的特征进行收集和提取。
根据Bayes公式:
我们做如下的约定和说明:
(1)根据要求我们把程序分为正常程序 A1和恶意程序A2两大类别。显然 P (A1) + P (A2) = 1满足完备性的条件。
(2)根据前面叙述,我们将检测到的特征设为 Bi,程序中出现特征 Bi的概率为 P (Bi) 。 i = 1 ,2,3,4...。如果一个检测到程序有几个特征码,则表示为 P (Bi, Bj, Bk),为了简单起见令 B = (Bi, Bj, BK) ,P(B ) = P(Bi, Bj, BK)。B表示检测到特征Bi, Bj, BK, P (B)表示待检测程序同时具有 Bi, Bj, BK特征的概率。
则Bayes改写为
公式1表示检测到程序具有特征B的情况下,判断该程序属于恶意或者正常程序的概率。
恶意程序的判别:合理的判别准则应该是根据对程序特征检测,判决准则如下:
根据 Bayes公式,我们有 P (A1, B ) = P(B)P(A1|B),P(A2,B ) = P(B)P(A2|B)代入判决准则得到:
则判断程序为正常程序,否则为恶意程序。
进一步变换上面公式得到:
则为正常程序。
或者通过似然比门限值来判断:
观察公式4我们得到如下结论:
P(B| Ai)是一个先验概率,可以分别通过统计病毒库程序和正常程序的特征来得到。例如以下为几个常用函数的统计值:
将这些先验概率数据进行保存,以便后面病毒检测中使用。
随着计算机网络技术的不断发展,计算机给经济、文化、军事和社会活动带来更多便利的同时,也带来了相当巨大的安全挑战。如今不断出现各种各样的新病毒对目前的病毒检测方法和机制提出了严峻的挑战,本文旨在运用当前模式识别与智能检测技术的理论和方法来解决目前病毒检测所遇到难题而提出的解决方案。
[1]程胜利.谈冉等.计算机病毒与其防治技术.清华大学出版社.2004.
[2]张仁斌,李钢,侯整风.计算机病毒与反病毒技术.清华大学出版社.2006.