利用特征码技术的静态杀毒引擎 特征码的选取 在进入程序的详细讲解之前,先来讲一下对于病毒程序的特征码通常是如何选取出来的,以及特征码的结构是什么样子的。通常选择特征码是按照以下思路。
1、获取一个病毒程序的长度,根据长度可以将文件分为几份,份数根据样本长度而定,可以是3~5 份,也可以更多。分成几段获取特征码的方法可以很大程度上避免采用单一特征码误报病毒现象的发生,也可以避免特征码过于集中造成的误报。
2、每份中选取通常为16 或32 个字节长的特征串。
在选取时,应该采取如下的原则:
1、如果选出来的信息是通用信息,即很多文件该位置特征码技术速度快,准确率高不能对付变形病毒或加密病毒静态广谱特征扫描技术
可以检测部分变形病毒误报率高启发式扫描技术(静态扫描+ 未知特征)误报率低,能检测变形病毒和病毒变种对未知病毒的检测能力较低行为判定技术基于强大而完整的虚拟机技术能够对未知病毒进行判别,对标准病毒准确率高实现难度大,速度慢都是一样的信息,那么舍弃,调整偏移量后重新选取。
2、如果选取出来的信息是全零的字节。那么也要调整偏移后重新选取。
关键数据结构 这一部分我们来解决病毒库的问题,顾名思义,这是一个记录病毒二进制特征的数据库。在本文这个例子中,我们使用如下的方法来记录每一个病毒:
1、我们把一个病毒分成不同的块,在每一块中取一个特征,用一个名为VSIGNATURE 的结构(下面会详述)来描述;
2、用一个名为VRECORD 的结构来把一个病毒的所有VSIGNATURE 组织在一起,这样就构成了对一个病毒的完整描述;
3、把这些完整的描述用链表组织起来,就是我们的病毒数据库了。
下面就来看看上面提到的两个重要结构VSIGNATURE和VRECORD。一个VSIGNATURE 是一个特征,很多个特征组成了一条病毒记录,也就是一个VRECORD。
typedef struct tagVSIGNATURE { BAV_SIGN_TYPE eType; DWORD dwOffset; DWORD dwSize; BYTE Signature[MAX_SIGNATURE_LEN]; }VSIGNATURE,*PVSIGNATURE; typedef struct tagVRECORD { int nSize; DWORD dwVirusID; DWORD dwSignCount; PVSIGNATURE pVSing[8]; DWORD dwTreatCount; PVTREATMENT pVTreat[8]; }VRECORD,*PVRECORD; |
VSIGNATURE结构是用于存放单一特征码的,其中的eType 成员变量是一个枚举结构,用来定义特征码的类型,这里演示工程里目前我们只定义了一种简单文件特征。dwOffset 成员存储该特征码的偏移量。dwSize 成员存储特征码的长度。字节型的Signature数组成员存放特征
码串,最大长度由 MAX_SIGNATURE_LEN 宏控制,目前为32 字节。
VRECORD 结构用于存放病毒库中每个病毒记录的内容。其中nSize用于控制结构的版本,目前我们不用过多关心。dwVirusID成员指定病毒的ID 编号。dwSignCount成员存放特征码(VSIGNATURE)的段数,也就是对于该病毒取了多少段特征码。pVSing 数组成员存放每段特征码
的内容,这里用数组是为了演示方便,以后我们会改为可变长度的数据结构。dwTreatCount成员存放处理该病毒的方法数量。pVTreat数组成员存放处理该病毒的每种方法的内容。这两个成员要到我们增加杀毒方法的时候才会用到。
下面来看一个具体的例子,eicar测试病毒的第一条特征是这样的:
{ BS_PHY_FILE, 0, 32, 0x58, 0x35, 0x4F, 0x21, 0x50, 0x25, 0x40, 0x41, 0x50, 0x5B, 0x34, 0x5C, 0x50, 0x5A, 0x58, 0x35, 0x34, 0x28, 0x50, 0x5E, 0x29, 0x37, 0x43, 0x43, 0x29, 0x37, 0x7D, 0x24, 0x45, 0x49, 0x43, 0x41, } |
它表明这是一个简单文件特征,特征起始地址0,特征长度32,后面32 个字节是具体特征值。