反病毒特征码技术
2018-02-22 23:33:13
  • 0
  • 0
  • 2

在反病毒引擎中,特征码扮演着至关重要的角色。特征码一般是用于判定文件或缓冲区是否包含恶意代码的一串散列值或字节码。

所有反病毒引擎自始至终都在使用特征码技术。尽管具体形式多种多样,但特征码一般是一串包含判断文件或缓冲区中是否存在已知恶意文件特征的短小散列值或字节码。散列通过特定的算法(比如CRC或MD5 )生成散列值,以作为特征码使用。这类算法计算速度快,可以在每秒内计算许多次,且不会消耗大量资源。因为特征码算法很容易执行且运行速度快,所以它是反病毒工程师最常用也最偏爱的恶意软件检测方法。

典型特征码

①字节流

字节流是最简单的反病毒特征码形式,一般不出现在正常文件中,而是仅限于恶意软件中。比如,要侦测欧洲计算机反病毒协会( EICAR ) 的测试样本文件,反病毒引擎只需匹配搜索下面这段完整字符串:

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

如你所见,侦测病毒最简单的方式就是匹配特征字符流,因为其简单而快速。同时,任何人都可以查找到许多稳定有效的字符串匹配算法 ( 比如Aho-Corasick.Knuth-Morris-Pratt.Boyer-Moore等),不过这类算法在容易实现的同时也会出现一些问题: 如果正常文件中也带有与恶意软件相似的字符串,就会发生误报,也就是说正常文件被反病毒软件当成恶意软件查杀了。的确,很难预测到底有多少反病毒软件会查杀带有上面EICAR样本特征字节码的文件。

②校验和

目前反病毒最常用的特征码匹配技术是基于计算匹配CRC实现的。循环冗余检查 ( cyclic redundancy check,CRC) 算法基于错误侦测技术,常用于检测或校验数据传输或者保存后可能出现的错误。该算法的实现原理是,取一个缓冲区的内容作为传人值,经过计算,生成一段校验和形式的、长度一般为4字节的散列 (如果使用的是CRC32的话就是32位),接着,反病毒程序会将整个或所选的部分缓冲区或文件计算对应的CRC校验和与特定的恶意软件特征进行对比。以前面的EICAR病毒测试样本文件为例,其CRC32校验和为0x685|CF3C。反病毒引擎会通过计算整个缓冲区而不是部分数据 (即,第一个2 Kb大小的代码块,最后一个2 Kb大小的代码块,以此类推 ) 的CRC32校验和,或分析文件划分出来的特定部分( 即,校验PE或ELF文件的特定区块) 来侦测测试样本文件。

从目前的分析情况来看,几乎所有反病毒软件都在使用CRC32算法。但是,在某些情况下,反病毒引擎不会使用原生的CRC32算法,而是使用改进版的算法。比如,在这类被修改过的算法中,算法使用的常量表或计算的回合数会被修改。当你在分析反病毒产品的特征码技术时,必须要注意到这点。这些修改过的CRC32算法生成的校验和可能会和原生的数值有一些差异,也因此可能会带来一些麻烦。

③定制的校验和

大多数反病毒引擎都会使用自研的类CRC特征码算法。

④加密散列算法

理想的加密散列算法有四个特性:

  • 针对传入的任何数据都能轻松计算出散列值
  • 加密散列值必须经过计算才会生成
  • 更改数据时对应的加密散列值都会变化
  • 一个散列值只能对应一段数据特征

高级特征码

①模糊散列算法

不同于前面提到的加密散列算法,模糊散列特征码技术不是针对单文件进行查杀,而是针对文件集合进行检测查杀。和加密散列不同的是,模糊散列有以下特征

  • 变动小或根本无变动 使用模糊散列算法,样本文件的细小变动对计算出的数值影响很小,只对改动的部分有影响;而在加密散列算法中,则会得出完全不同的散列值。
  • 没有进行混淆 可以很清楚地依次分辨出键与生成的模糊散列值。例如,在第一区块中的细小改动,只会影响第一次生成输出的字节。
  • 理想的重复率 重复率因不同的业务场景而异。例如,检测垃圾邮件的时候碰撞率稍高也是可以接受的,但在进行恶意软件侦测的时候重复率高就不合适了 (因为高重复率意味着高误报率)。

想要绕过模糊散列校验算法,因为细小的改动不会造成模糊散列值得大变动,所以攻击者需要对恶意软件进行一番大改动。假设使用ssdeep算法,让编写的实验反病毒引擎在Ubuntu Linux平台上去侦测/bin/ls

$ md5sum ls
指定文件的MD5值
$ ssdeep ls
区块大小、散列值、加上文件名的散列

在文件末尾增加一个字节,例如字符A,然后重新计算一次MD5值和模糊散列值

$ cp ls ls.mod
$ echo "A" >> ls.mod
$ ssdeep ls.mod

对比两次的输出结果可以看出来,MD5的值彻底改变了,但是ssdeep散列值只变动了一个字节,如果开发者通过这串模糊散列去九三变动情况,将会发现新生成的文件同旧文件异常相似,因此就会将新生成的样本提示为病毒。再来看接下来的操作:

$ cp ls ls.mod
$ cat /bin/cp >> ls.mod
$ ssdeep ls.mod

通过执行这几条我们可以发现几乎整个模糊散列值都有了明显的变化,这样就可以绕过这种算法的特征码检测了。但是,绕过特征码检测需要变动位置的数量由区块大小决定: 如果区块大小取决于分配的缓冲区的大小且不恒定,绕过此类特征码检测就较为容易。例如,让我们再试一次,这次选用DeepToad.该工具允许你配置校验选取区块的大小G 将区块大小配置为512字节,然后计算两个文件的散列:

$ deeptoad -b=512 ls
$ deeptoad -b=512 ls.mod

这次通过把cp附加到原文件ls上的技巧就无法绕过特征校验算法了。有两个原因: 第一,因为DeepToad校验选取区块大小固定,而不是像ssdeepー样是动态选择的;第二,因为DeepToad校验了三个不同的散列值,由分号分隔,且前两个散列值完全匹配。简而言之,绕过模糊散列算法取决于选取校验区块的大小以及大小的数值。

②基于程序图的可执行文件散列算法

一些高级反病毒产品中会带有基于程序图的可执行散列特征校验算法。程序图可以分为两种不同类型的:

  • 调用图:展示程序中各函数调用关系的图标(展示程序中所有调用和被调用的函数)
  • 流程图:展示所有函数基础区块和关系的图标(部分只有一个入口点和一个出口点的代码)

反病毒引擎中的代码分析引擎可能会使用从调用图( 一张包含程序中所有函数的图表)或流程图( 一张展示所有函数基础区块和关系的图表) 中提取的特征信息进行分析,很显然,这类算法操作 十分消耗资源,类似IDA这样的工具可能需要花费数秒到数分钟不等的时间去分析整个软件结构。反病毒引擎不可能花费几秒或几分钟去分析单个文件,所以一般会选取部分指令和基础区块进行分析,或者设置一个超时值,超过最大时间限制就不再继续分析

基于程序图检测恶意软件族的特征引擎一般是多态的,尽管真实的指令会因改动而有所不同,但是调用图和流程图一般来说不会有变动,因此,反病毒软件工程师会使用特定函数的基础区块的图形特征去解析恶意软件,比如检测恶意软件解压缩或解密层流程。

如果没有设定一些限制或设定不正确,这种办法也会带来一些性能上的问题,也可能会和其他特征码算法一样产生误报,比如,如果恶意软件作者发现反病毒软件基于恶意软件中某一函数的流程图特征,对自己编写的恶意软件进行了检测查杀,他可能会模仿正常软件的函数,编写恶意程序相关函数(参见流程图).他们可能会参考Windows操作系统上的notepad.exe或其他一些正常的软件,因为恶意软件作者的改动导致病毒的新变种同其他正常软件的图表特征相似,所以反病毒工程师发现需要针对新变种提取新的特征,而不是在原有特征基础上进行一些修改

对于病毒作者来说,以下方法可以绕过基于程序图的可执行文件散列算法。

  • 同之前介绍的那样,变更病毒程序流程图或调用图的样式,让它们看起来是正常软件的函数。
  • 给病毒程序加上反调试功能,这样因为不理解单个或多个调试指令,病毒软件的代码分析引擎就无法反汇编程序内的函数逻辑。
  • 结合反调试和错误断点的技巧,因为错误的指令或代码混淆了反病毒引擎的分析逻辑引擎无法正确判断什么时候要跳转,也无法分析路径是true还是false,
  • 通过超时技巧让恶意软件的流程图变得复杂,这样反病毒引擎在进行代码分析的时候就会因为超时而终止分析。超时终止会让代码分析引擎无法分析部分或全部函数的流程图。

很明显,基于程序图的特征码检测技术相较于仅基于字节码的特征检测技术要强大得多;但是,有时出于性能的考虑不会使用这种检测技术。这也是一些反病毒厂商不会大规模使用这种技术的原因: 不太实用。

 
最新文章
相关阅读