一种基于虚拟执行模式的Flash漏洞检测方法
技术领域
本发明涉及一种基于虚拟执行模式的Flash漏洞检测方法。
背景技术
Adobe公司的Flash Player是一款目前使用极为广泛的客户端播放器,能够在各种主流操作系统、浏览器、移动电话和移动设备上提供功能强大与内容丰富的视频体验。现在,几乎绝大部分PC机或其它终端都装有Flash Player,但与此同时,Flash Player漏洞也日益增多,并对互联网的安全造成了严重的威胁。
根据CVE公布的漏洞报告,Flash漏洞数量目前仍呈增长趋势,Flash Player已成为高危漏洞最多的黑客攻击重灾区。而2011年十大安全漏洞当中,FlashPlayer共曝出四次高危漏洞,其危险程度已超过微软Windows操作系统。鉴于Flash Player饱受诟病的安全性,IOS等操作系统甚至已拒绝支持Flash,以保证客户端安全。
Flash漏洞检测是对目标Flash文件是否为利用Flash漏洞编写的恶意文件进行检测的一种方法,通过检测,可以事先发现恶意Flash文件,阻止用户访问,从而保证用户的网络安全。
目前传统的Flash漏洞检测方法主要有三种:
(1)基于特征码匹配的Flash漏洞文件扫描
此方法类似于传统杀毒软件的文件扫描,即将待检测的Flash文件以二进制流的形式打开,通过匹配事先设定的特征码来确定该文件是否具有漏洞。这种对包含漏洞的Flash文件进行扫描的方法,适用面较窄,且效果不佳。
(2)基于静态分析代码的Flash漏洞检测
此方法首先将Flash文件中的ActionScript代码进行反编译,然后再对其代码进行静态分析,检测是否具有触发某一漏洞的特定条件。如根据CVE-2011-2134的漏洞描述,当代码中包含一个深度大于16的表达式时,会导致溢出并触发漏洞,例如:"A".match(/(((((((((((((((((.*)))))))))))))))).)*/g);。因此当检测到具有该类表达式时,则成功检测出漏洞。
由于大部分Flash漏洞需要根据变量值等当前状态信息进行匹配,而静态分析代码无法得到此类执行Flash代码后的状态信息,故该方法效果不佳。
(3)基于虚拟执行的Flash漏洞检测
该方案的原理主要是将Flash文件在Flash播放器的虚拟机(即AVM2,已开源)中执行,通过其行为来检测是否具有漏洞。如大部分缓冲区溢出漏洞,就可根据Flash是否崩溃,堆或栈是否溢出来判定。
但该方案仍存在问题。如怎样实现执行Flash文件中的所有ActionScript代码尚需解决,因为攻击者可以将漏洞利用代码编写成需要特定触发条件才会执行,如点击Flash中某一按钮,或使用Firefox浏览器打开时才会执行等。此外,传统虚拟执行方法需要运行Flash文件,则在对大量Flash文件进行漏洞检测时,效率较低。
发明内容
本发明所要解决的技术问题是提供一种基于虚拟执行模式的Flash漏洞检测方法,该基于虚拟执行模式的Flash漏洞检测方法具有误判率低,执行效率高的特点。
发明的技术解决方案如下:
一种基于虚拟执行模式的Flash漏洞检测方法,包括以下步骤:
步骤1:将待检测的Flash文件进行反编译,得到ActionScript代码;
步骤2:对ActionScript代码进行单词扫描及词法分析,即将ActionScript代码转换成单词流,并对每个单词的类型进行分析,单词的类型包括保留字、标识符、符号、数字;
步骤3:构建生成树:
以生成树存储ActionScript代码:生成树中每个结点用于存储ActionScript的一行语句,若某结点具有子结点,则每个子结点存储的ActionScript语句是其父节点的ActionScript语句的子语句;
步骤4:对每个结点中的语句进行结构分析,得到类结构信息,其中语句结构包括类定义语句、类成员变量定义语句及类的成员函数定义语句;在分析ActionScript代码结构时,对代码逐行进行扫描,若发现关键字“class”则为类定义语句,关键字“function”则为类的成员函数定义语句;若找到关键字“var”或“const”则为类成员变量定义语句;
标记所有函数的状态为“未执行”;
步骤5:基于类结构信息生成虚拟执行流程,并将虚拟执行流程放入虚拟执行流程栈中;
步骤6:漏洞检测过程:
从虚拟执行流程栈依次取出一个流程并执行,将该流程中调用过的函数标记为“已执行”状态,在流程执行过程中进行漏洞规则匹配,如果匹配成功,则提示存在漏洞,否则执行下一个从虚拟执行流程栈取出的流程;直到最后一个流程执行完成;
步骤7:输出漏洞检测结果,检测结束。
在步骤6的流程执行过程中,判断是否遇到分支语句,若遇到分支语句,根据判定覆盖原理新增虚拟执行流程,存入虚拟执行流程栈中;
在步骤6的流程执行过程中,当虚拟执行流程栈为空时,即虚拟执行流程栈中的流程都已经执行完毕时,进一步判断是否仍有函数状态为“未执行”,如果是,则为未执行的函数生产新的虚拟执行流程并存入虚拟执行流程栈中,并返回到步骤6的开始;否则跳转至步骤7。
漏洞规则匹配的过程为:一个虚拟执行流程执行完毕,根据当前变量信息进行漏洞规则匹配,若符合某漏洞规则,则表示该Flash文件具有漏洞,若所有漏洞规则都不符合,则表示该Flash文件是安全的。
漏洞规则存储在漏洞规则库中,漏洞规则库是根据CVE(CommonVulnerabilities & Exposures,中文名称为公共漏洞与暴露,是国际上著名的发布各种漏洞信息的字典表)关于Flash的漏洞报告所编写的函数集,每个函数对应一个Flash漏洞匹配规则。
所述虚拟执行流程的包括如下设置:
1)虚拟执行流程包含所需执行代码段的开始结点m_pBegNode和结束结点m_pEndNode,两结点确定代码段的范围;包含一个指针m_pNode,指示当前所执行语句的结点,指针的初始位置为虚拟执行流程的开始结点;
2)虚拟执行流程包含两个指针m_pFunction和m_pClass,m_pFunction指示所需执行代码段所属的函数,m_pClass指示所需执行代码段所属的类;
3)每个虚拟执行流程包含一个变量m_vars,用于存储该流程所需的所有变量信息。
对本发明技术路线的说明:
(1)反编译Flash文件,得到ActionScript代码
由于Flash编译器在编译ActionScript代码时,将其转换成了一种称之为“字节码”的中间码格式,故需首先进行反编译。
(2)单词扫描及词法分析
反编译ActionScript代码后,为了方便进行后续的分析及虚拟执行,需要对代码进行单词扫描,即将ActionScript代码转换成单词流,并对每个单词的类型进行分析。
例如对于语句“var num:int=10;”,单词扫描及词法分析过后,应生成如下单词流("var",保留字),("num",标识符),(″:",符号),("int",保留字),("=",符号),("10",数字),(";",符号)。
(3)构建生成树
为方便后续的虚拟执行,需要对单词流进行整形,以生成树的结构存储ActionScript代码。树中每个结点存储ActionScript的一行语句,若某结点具有子结点,则每个子结点存储的ActionScript语句是其父节点的ActionScript语句的子语句。
生成树构建后,在虚拟执行过程中,只需要从开始结点处,对其进行先序深度遍历即可,且在查找上层语句时较方便。
(4)分析ActionScript代码结构
构建完ActionScript代码的生成树后,此时并不虚拟执行任何代码,而是对其类结构进行分析,即包含哪些类,类的成员函数与成员变量有哪些,其类型是什么(与C++语言的头文件类似),并设计一个类或数据结构保存这些信息。其具体分析方法是先序深度遍历生成树,对于每个结点中的语句,若找到关键字“class”则为类定义语句,此时关键字“class”后的第一个单词为类名,再找到关键字“extends”则紧跟其后的第一个单词为该类的基类名;在类定义语句结点的孩子结点中,若找到关键字“var”或“const”则为类成员变量定义语句,此时“var”或“const”后第一个单词为变量名,“:”后第一个单词为变量类型,“=”后的单词为变量值;在类定义语句结点的孩子结点中,若找到关键字“function”则为类的成员函数定义语句,此时关键字“function”后的第一个单词为函数名,关键字“(”和“)”之间的单词为该函数的参数变量。
(5)虚拟执行ActionScript代码
与Flash Player播放Flash文件不同,这里并不真正执行ActionScript代码,由于Flash缓冲区溢出漏洞大多只与变量与内存空间相关,故虚拟执行时只关心代码中的各变量改变,而不关心各功能的实现。
虚拟执行流程的初始化,是根据可能最先执行的函数生成虚拟执行流程。由于ActionScript不同于C/C++,没有类似main()这样确定的入口函数,故只能猜测哪些可能是最先执行的函数,这样做的目的也是为了尽量模拟真实的执行环境与顺序。实际上此类函数的选择对漏洞检测结果影响不大,一般将各个类的构造函数及事件响应函数作为可能最先执行的函数。初始化完毕后,依次选取各个虚拟执行流程进行虚拟执行。
虚拟执行时,遇到功能实现代码或其它与变量变化无关的代码不需要实现其执行,如添加事件监听器或载入对象,以简单方法的实现并提高执行效率。但执行诸如内存空间的分配与回收,或变量的新建、赋值与修改等,则记录该变量名称,类型,值以及作用域。
若虚拟执行过程中,遇到分支语句,则根据判定覆盖的原理,根据每个分支的条件表达式修改相应变量的值,以覆盖所有分支语句,并为其新增虚拟执行流程,以待后续的执行。
(6)匹配漏洞的触发条件
每当一个虚拟执行流程执行完毕时,提取当前虚拟执行流程的变量信息,并遍历查询漏洞规则库,判断目前条件或存储的变量值是否符合漏洞触发条件。漏洞规则库是根据CVE发布的Flash的漏洞报告的漏洞原理,将其编写成一个个漏洞匹配函数(根据漏洞报告中的漏洞原理编写漏洞匹配函数,本领域技术人员无需经过创造性劳动即可完成),每个函数对应一个Flash漏洞匹配规则。若符合,则提示有漏洞,若当所有漏洞规则都与当前变量信息不匹配时,则可以认为该Flash文件是安全的。
(7)对从未执行函数进行虚拟执行
当虚拟执行流程队列中,所有的虚拟执行流程都执行完毕,还需对ActionScript代码中所有函数再次进行扫描,若此时发现有函数的m_IsExecute字段值为false,则表示该函数从未被虚拟执行过,则为该函数新增虚拟执行流程,并进行虚拟执行。当此类流程也执行完毕后,则表示所有函数都至少被执行了一次。
有益效果:
本发明的基于虚拟执行模式的Flash漏洞检测方法,与静态代码分析方法相比,采用判定覆盖的方式,弥补了基于虚拟执行方法当中不能虚拟执行所有ActionScript代码的缺陷;能检测出更多的Flash漏洞数量,其正确率依赖于ActionScript代码的复杂程度。对于大多数包含漏洞的Flash文件,编写者往往注重漏洞利用的实现,而不会将其ActionScript代码写得过于复杂与繁琐,故正确率较静态代码分析方法和虚拟执行方法更高。在误判率方面,由于对Flash漏洞的检测是根据CVE的漏洞报告进行精确漏洞规则匹配,其变量信息来源于虚拟执行后的结果,因而能最大可能的保障误判率小,正常的ActionScript代码很难满足以上要求。此外,与虚拟执行方法相比,由于该方法只模拟执行流程中变量的变化,而并不真正执行ActionScript代码中的方法,故效率更高。
综上说述,该方法通过采用判定覆盖的方式,虚拟执行所有ActionScript代码,并根据执行完毕后的变量状态及其它信息进行漏洞规则匹配,以检测是否具有漏洞,具有正确率高且效率高的优点。
附图说明
图1为基于虚拟执行模式的Flash漏洞检测方法的流程图;
图2为生成树构建范例对应的示意图。
具体实施方式
以下将结合附图和具体实施例对本发明做进一步详细说明:
一种基于虚拟执行模式的Flash漏洞检测方法,包括以下步骤:
步骤1:将待检测的Flash文件进行反编译,得到ActionScript代码;
步骤2:对ActionScript代码进行单词扫描及词法分析,即将ActionScript代码转换成单词流,并对每个单词的类型进行分析,单词的类型包括保留字、标识符、符号、数字;
步骤3:构建生成树:
以生成树存储ActionScript代码:生成树中每个结点用于存储ActionScript的一行语句,若某结点具有子结点,则每个子结点存储的ActionScript语句是其父节点的ActionScript语句的子语句;
步骤4:对每个结点中的语句进行结构分析,得到类结构信息,其中语句结构包括类定义语句、类成员变量定义语句及类的成员函数定义语句;在分析ActionScript代码结构时,对代码逐行进行扫描,若发现关键字“class”则为类定义语句,关键字“function”则为类的成员函数定义语句;若找到关键字“var”或“const”则为类成员变量定义语句;
标记所有函数的状态为“未执行”;
步骤5:基于类结构信息生成虚拟执行流程,并将虚拟执行流程放入虚拟执行流程栈中;
步骤6:漏洞检测过程:
从虚拟执行流程栈依次取出一个流程并执行,将该流程中调用过的函数标记为“已执行”状态,在流程执行过程中进行漏洞规则匹配,如果匹配成功,则提示存在漏洞,否则执行下一个从虚拟执行流程栈取出的流程;直到最后一个流程执行完成;
步骤7:输出漏洞检测结果,检测结束。
在步骤6的流程执行过程中,判断是否遇到分支语句,若遇到分支语句,根据判定覆盖原理新增虚拟执行流程,存入虚拟执行流程栈中;
在步骤6的流程执行过程中,当虚拟执行流程栈为空时,即虚拟执行流程栈中的流程都已经执行完毕时,进一步判断是否仍有函数状态为“未执行”,如果是,则为未执行的函数生产新的虚拟执行流程并存入虚拟执行流程栈中,并返回到步骤6的开始;否则跳转至步骤7。
漏洞规则匹配的过程为:一个虚拟执行流程执行完毕,根据当前变量信息进行漏洞规则匹配,若符合某漏洞规则,则表示该Flash文件具有漏洞,若所有漏洞规则都不符合,则表示该Flash文件是安全的。
漏洞规则存储在漏洞规则库中,漏洞规则库是根据CVE(CommonVulnerabilities & Exposures,中文名称为公共漏洞与暴露,是国际上著名的发布各种漏洞信息的字典表)关于Flash的漏洞报告所编写的函数集,每个函数对应一个Flash漏洞匹配规则。
所述虚拟执行流程的包括如下设置:
1)虚拟执行流程包含所需执行代码段的开始结点m_pBegNode和结束结点m_pEndNode,两结点确定代码段的范围;包含一个指针m_pNode,指示当前所执行语句的结点,指针的初始位置为虚拟执行流程的开始结点;
2)虚拟执行流程包含两个指针m_pFunction和m_pClass,m_pFunction指示所需执行代码段所属的函数,m_pClass指示所需执行代码段所属的类;
3)每个虚拟执行流程包含一个变量m_vars,用于存储该流程所需的所有变量信息。
实施例1:
图1是本发明的流程图,步骤如下:
(1)反编译Flash文件,得到ActionScript代码
由于Flash编译器在编译ActionScript代码时,将其转换成了一种称之为“字节码”的中间码格式,故需首先进行反编译。
(2)单词扫描及词法分析
反编译ActionScript代码后,为了方便进行后续的分析及虚拟执行,需要对代码进行单词扫描,即将ActionScript代码转换成单词流,并对每个单词的类型进行分析。
例如对于以下语句:var num:int=10;,单词扫描及词法分析过后,应生成如下单词流("var",保留字),("num",标识符),(":",符号),("int",保留字),("=",符号),("10",数字),(";",符号)。
(3)构建生成树
为方便后续的虚拟执行,需要对单词流进行整形,以生成树的结构存储ActionScript代码。树中每个结点存储ActionScript的一行语句,若某结点具有子结点,则每个子结点存储的ActionScript语句是其父节点的ActionScript语句的子语句。
在构建生成树结构时,先新建一个结点指针,代表指向父节点,初始值为树的根结点。然后新建一结点变量,再对单词流进行遍历,每遍历一个单词时,将其加入到该结点当中。当遍历到分号时,表明该行语句结束,将该结点链接到当前父节点的子结点当中;当遍历到左大括号时,表明其后为子语句,此时将现有结点链接至父节点的子结点当中,然后指针指向该结点,然后再进行遍历;当遍历到右大括号时,表明子语句结束,将该结点链接至父节点的子结点后,指针指向其父结点的下一个结点。根据该规则,最后直至所有单词都遍历结束。图2为一段ActionScript示例代码对应的生成树结构。
对每个结点中的语句进行结构分析,得到类结构信息,其中语句结构包括类定义语句、类成员变量定义语句及类的成员函数定义语句等;在分析ActionScript代码结构时,对代码逐行进行扫描,若发现关键字“class”则为类定义语句,关键字“function”则为函数定义语句。然后用一种数据结构将该类信息存储起来,以便后续的分析及执行。
存储类信息的类设计结构如下:
初始化虚拟执行流程时,通过分析函数名是否与类型相同,来判断构造函数,通过分析函数的参数列表中是否含有关键字“Event”来判断事件响应函数,并为这两种函数建立虚拟执行流程。
虚拟执行流程的类设计如下所示:
其中变量信息的初始内容,为所属类的成员变量及所属函数的参数变量。
虚拟执行过程中,若遇到变量的新增、赋值、修改等操作,需要对其进行记录,以备后续漏洞规则匹配之用。
存储变量信息的类设计如下所示:
若在虚拟执行过程中,遇到if语句,switch语句,while语句,for语句这四种分支语句时,则根据判定覆盖的原理,修改相应变量信息,并新增虚拟执行流程。例如遇到如下语句:
if(a1>=0){...}
else if(a1<0){...}
若执行到该if语句时,原来变量a1的值大于等于0,则新增一个虚拟执行流程,将其中的变量a1的值修改为小于0(如值为-1),并将该虚拟执行流程的开始行号设置为条件表达式(a1<0)后的语句块内的首条语句。
一个虚拟执行流程执行完毕以后,需要根据当前变量信息进行漏洞规则匹配,若符合某漏洞规则,则表示该Flash文件具有漏洞,若所有漏洞规则都不符合,则表示该Flash文件是安全的。
如对于CVE-2011-2137漏洞,其规则是:若发现一类型为FileReference的变量进行save操作,且操作的参数变量中存在一个长度大于0x4000的string类型变量,则匹配成功,提示有漏洞。
当所有虚拟执行流程都执行完毕后,需检查是否仍有函数从未执行过。若存在该类函数,则为其新增虚拟执行流程,并依次虚拟执行。
采用本发明方法进行Flash漏洞检测,与静态代码分析方法相比,能检测出的Flash漏洞数量更多,且采用判定覆盖的方式,弥补了基于虚拟执行方法当中不能虚拟执行所有ActionScript代码的缺陷。此外,本发明的执行效率较基于虚拟执行的方法也更高。
采用本发明方法进行Flash漏洞检测,其正确率依赖于ActionScript代码的复杂程度。对于大多数包含漏洞的Flash文件,编写者往往注重漏洞利用的实现,而不会将其ActionScript代码写得过于复杂与繁琐,故正确率较静态代码分析方法和虚拟执行方法更高。在误判率方面,由于对Flash漏洞的检测是根据CVE的漏洞报告进行精确漏洞规则匹配,其变量信息来源于虚拟执行后的结果,正常的ActionScript代码很难满足以上要求,故误判率极低。
CVE所有漏洞报告及对应的漏洞利用的样本文件均可在其网站上免费下载,抽选了其中十个较新的Flash漏洞对应的样本文件,表1是分别采用静态分析代码方法和本发明方法是否能成功检测出漏洞的结果:
表1静态代码分析方法与本发明方法检测结果比较
漏洞名称 |
静态代码分析方法 |
本发明方法 |
CVE-2011-2134 |
√ |
√ |
CVE-2011-2135 |
|
√ |
CVE-2011-2136 |
|
√ |
CVE-2011-2137 |
|
√ |
CVE-2011-2138 |
|
√ |
CVE-2011-2139 |
|
√ |
CVE-2011-2140 |
√ |
√ |
CVE-2011-2414 |
|
√ |
CVE-2011-2416 |
|
√ |
表1中数据能够表明本发明所提供的Flash漏洞检测方法明显优化于静态代码分析方法,在相同条件下,能够检测出更多的漏洞。