基于缓冲区溢出的数据驱动型漏洞检测系统总体设计与实现*

2015-09-09 09:45文雪巍秦秀媛王凤领
关键词:词法源代码缓冲区

文雪巍,秦秀媛,王凤领

(黑龙江财经学院)

0 引言

长期以来,计算机信息安全这个问题一直在困扰着人们,特别是随着系统软件和应用软件的广泛使用,人们发现存在漏洞问题非常普遍.在这些漏洞中,数据驱动型漏洞达到了半数以上.数据驱动型漏洞是指由数据不正确使用引起的溢出产生的漏洞,它分为缓冲区溢出漏洞和格式化字符串漏洞等[1].

为了减少这种漏洞的出现,数据驱动型漏洞的检测技术成为了信息安全研究的一个重要课题.原有的检测方法只能对漏洞语句做到词法分析和语法分析.该文在此基础上提出了语义分析的静态检测方法,并实现了一个原型检测系统[2].该系统可以在软件开发完成后,在软件开发小组内部进行检测,检测出软件中是否存在缓冲区溢出漏洞,以及漏洞出现的位置,为软件开发人员提供了更准确的检测依据.

1 原型检测系统的总体设计

这种面向语义分析的原型检测系统是以语法分析和编译原理中的词法分析为基础的,采用Wagner对缓冲区的数学描述方法,以实现语义方面的检测.主要由四个模块组成原型检测系统,分别是创建程序执行流程模块、综合处理模块、词法分析模块和缓冲区预先搜索模块四个部分.原型检测系统的整体结构图如图1所示.

图1 原型检测系统结构图

根据图1所示,其工作流程是:原型检测系统首先读入源代码文件,如果有多个源代码文件就逐个读入.程序有两个分支,“词法分析模块”将源代码“粉碎”成一个token字序列(一个token字就是一个有属性标记的符号,比如,包括属性有,标识符,数字,关键字等).“词法分析模块”将token字序列传递给“缓冲区预先搜索模块”(其实所谓的传递就是token字序列是全局变量,全局可见的),“缓冲区预先搜索模块”根据token字序列,将字符指针,字符缓冲区等内容从token字序列中“提取”出来,存入到固定的数据结构中(数据结构的描述在“缓冲区预先搜索模块”中).“创建程序执行流程模块”根据缓冲区列表和源程序的执行流程,对存在关系的缓冲区进行统计,比如,如果两个缓冲区简直存在关系,那么就在有向图中这两个节点之间添加一条边.“创建程序执行流程模块”得到一个缓冲区之间关系的有向图.“综合处理模块”获得token字串序列和流程有向图,加载漏洞函数数据库,根据该文提出的语义分析方法进行语义分析,最后将分析的结果输出到检测报告中.

2 原型检测系统模型的详细设计[3]

2.1 词法分析模块

2.1.1 词法分析算法

源代码文件的录入过程就是依靠词法分析实现的,其本质上是将源代码的源程序转换成众多的Token字.考虑到源程序各个部分的具体的内容互不相同,为了方便检测和控制,常常将不同的部分转换成特定的Token字进行具体的标记.如下所示,为常见的C语言类转换语句:

如果要词法分析上面的C语言语句,可以简单的将其划为四个部分即:数字、特殊字符、变量、关键字,他们分别对应着“1”、“=”、“b”、“int”,这样该C语言的四个部分具有了特定的属性,这样既实现了词法分析.类似的,可以对所有的源文件进行这样的词法分析.

2.1.2 词法分析算法流程

图2为词法分析算法流程图,也即Lex的工作流程.

图2 词法分析流程

源文件中各个部分都被赋予了特定的属性后,整个程序就转换成了一个Token字符序列,该序列有明显的独特性,且很多模块都可以检测这些Token序列,因此,源文件就很容易被搜索.需要注意整个过程的最基本操作就是词法分析[4].

2.2 缓冲区搜索模块

2.2.1 缓冲区的搜索方法

在源代码中开辟缓冲区可能会引起数据驱动型漏洞,因此必须对源程序中开辟的缓冲区进行具体的检测.一般要找到源程序中的某一个缓冲区,直接从缓冲区列表中读取即可,但是要注意这一缓冲区列表不是自动生成的,首先需要检测整个工程,进而根据不同缓冲区的特点创建而成.2.2.2 模块的算法流程

模块的算法流程显示了缓冲区搜索的整个过程,如图3所示.

找到并检测程序中的缓冲区,并给予其具体的定义,采用专用的数据进行表征进而将其存储在特定的区域.为了方便缓冲区的标记和定义,一般要在开辟缓冲区之前制定一个对应缓冲区具体属性的表.

2.3 创建程序执行流程模块

改进的Wagner处理方法.

在整数范围内Wagner方法比较常用,但是遇到有向图循环时,该处理方法就显得格外麻烦,因为需要在所有的字符串后都分别设置一个特别域.因此,为了降低处理过程的复杂性,可以有意的避免循环图的出现或者改变循环图为非循环图[5].

这里优化了Wagner方法,动态检测时只处理与之相关的缓冲区域,尽量降低对缓冲区的干扰和影响,涉及到的约束关系相对比较简单:

图3 缓冲区搜索流程

(1)最常见的约束关系是缓冲区的开辟和使用(常与缓冲区的大小相关);

(2)字符串的长度是否达到一定值,这时常常要考虑库文件中的一些函数,这种约束关系也是常常涉及到[6].

很明显,上面说到的约束关系要比普通Wagner方法简单很多,其十分有效的回避了循环图问题,用很少的约束就达到了目的.但是上面所述的约束也存在两个很大的缺陷:①不能把所有的缓冲区的信息都揭示出来;②没有涉及到堆溢出的处理方法即没有检测堆分配和堆指针的安全性.因此,大多时候在搜索模块必须解决上面所述的两个突出问题.一般,综合处理模块负责了程序执行流程模块的程序执行流程有向图和缓冲区预先搜索模块的缓冲区列表的创建,便于分析程序的语法和语义.

2.4 综合分析模块

图4是综合分析模块的算法流程.

综合分析模块分析检索缓冲区时必须先得到Token字串序列和开辟的缓冲区的列表,然后参照程序执行流程有向图及定义的危险函数,进而确定是否及哪里会出现溢出及有缺陷的语义和内容,并将判断结果及时的报告到相关文件中.

图4 综合分析流程

3 测试过程

该检测软件的测试过程包括两个点:一个是测试具有代表性的开源代码、另一个是测试存在溢出漏洞的缓冲区.使用上述两个测试过程进行系统检验可以得到较为完整的测试结果,检验系统是否能够正常运行.

为对检测系统做清晰的说明,举几个简单但是特别构造的具有缓冲区溢出漏洞的代码,给出原型系统的检测结果.代码1为:

从代码1可以发现,这段代码具有明显的数据驱动型漏洞.目的缓冲区buffer[10]中,开辟的空间大小为10字节,而源缓冲区“Hello a example”,包括’’共16字节,但从源缓冲区向目的缓冲区复制时,一定会发生溢出.

对代码1检测结果如图5所示:

图5 代码1检测结果

可以看到,词法分析的结果(Lex Analyse)是比较笼统的,只是简单的匹配后得到的,并没有明确的给出是否溢出或溢出点.而经过语义分析的补充(Semantic Analyse),可以看到语义分析的结果给出了明确的溢出点:”buffer@main()”以及缓冲区的使用情况:”10…10 bytes allocated,16…16 bytes used”,并给出明确的警告”Almost certainly a buffer over-flow”.

再例如,代码2所示:

代码2中有一个用户自定义函数,传给func函数的是一个字符指针,这个指针指向的是“my name is a small laborary”,长度为28字节.复制给buffer[10]时肯定后发生溢出.

对代码2的检测结果如图6所示:

图6 代码2检测结果

检测结果可以看到,经过语义分析检查到了缓冲区的溢出.

下面再看一个例子,具有数据驱动型漏洞的代码(源代码文件名为foobar.c):

上述源代码构造了典型的数据驱动型漏洞,并使用用户自定义函数、宏定义函数等,以测试程序的输出情况.

原型系统对上述源代码进行检测的结果(源代码文件名为foobar.c):

通过原型检测系统给出的结果,可以看出对于使用了危险函数但没有出现溢出只是给出警告,减少了误报、漏报的情况.而ITS4的检测结果是对每行都给出了警告,通过比较,原型检测系统检测的结果是完全可信的.

4 结束语

面向语义分析的原型检测系统同已有的检测方法相比,该检测方法实现了对缓冲区溢出漏洞更准确的检测,具有较低的误报率和很好的运行性能.但检测系统本质上还是对源程序进行静态扫描,依然存在着一些缺点.比如,系统生产的警告数量较多;对于一些代码较多、程序复杂的系统工程,检测速度会变慢,产生了大量的等待时间等.上述问题必须认真思考解决办法.

[1]宁慧,文雪巍.基于语义分析的数据驱动型漏洞检测方法[J].应用科技,2011.30–35.

[2]文雪巍.数据驱动型漏洞检测技术研究[D].哈尔滨工程大学,2011.62.

[3]刘松涛.用户界面原型方法的研究与应用[D].华中科技大学,2014.46.

[4]马灵春.程序理解中静态分析与抽取技术的研究及实现[D].浙江工业大学,2007.2.

[5]丁永尚,何福男.关于缓冲区溢出漏洞的解决方法[J].计算机应用系统,2010(3):193.

[6]于继江.基于危险函数的缓冲区溢出检测方法的研究与实现[J].2011(9):186.

猜你喜欢
词法源代码缓冲区
基于TXL的源代码插桩技术研究
软件源代码非公知性司法鉴定方法探析
基于网络聚类与自适应概率的数据库缓冲区替换*
基于语法和语义结合的源代码精确搜索方法
应用于词法分析器的算法分析优化
谈对外汉语“词法词”教学
一类装配支线缓冲区配置的两阶段求解方法研究
揭秘龙湖产品“源代码”
关键链技术缓冲区的确定方法研究
初涉缓冲区