一种基于程序图的栈缓冲区溢出脆弱性检测方法与流程

文档序号:17724849发布日期:2019-05-22 02:26阅读:163来源:国知局
一种基于程序图的栈缓冲区溢出脆弱性检测方法与流程

本发明属于信息安全技术领域,涉及一种基于程序图的栈缓冲区溢出脆弱性检测方法。



背景技术:

随着计算机技术的不断发展,各行各业对软件的需求越来越大,越来越多的人享受着信息系统带来的方便快捷。在信息技术不断发展过程中不可避免要面对的问题就是软件漏洞。在软件开发过程中开发人员都会犯一些错误,有些错误致命如果不及时找出来会造成很严重地后果。在目前所有的软件漏洞中,缓冲区溢出是很常见的安全漏洞之一。因此,软件脆弱性成因分析日益成为信息安全领域关注的重点。

缓冲区溢出产生的主要原因是向固定长度大的缓冲区中写入超出其预分配长度的内容,造成缓冲区中数据的溢出从而导致缓冲区的结构被破坏。攻击者借此构造假数据导致原有程序改变,最终获取控制权。1988年第一个蠕虫病毒在极短的时间内攻击了几百台电脑造成了巨大的影响。2001年名为codered的病毒导致了30多万台运行windows的计算机受到攻击,造成了巨大的经济损失。此外,还有很多利用shellcode进行远程溢出攻击的案例。目前公共漏洞库(cve)组织已经形成了一批在国际上颇具影响力的标准。美国国家漏洞库(nvd)对漏洞进行了统一命名、分类和描述,严格兼容cve,构建了全方位、多渠道的漏洞发布机制和标准化的漏洞修复模式。

c和c++语言的使用经常导致缓冲区溢出漏洞。目前,静态和动态技术是检测缓冲区溢出漏洞的主要技术。静态检测技术是指不运行被测程序本身,仅仅通过分析或检测源代码的语法和结构等来检测程序的准确性。也就是说在程序执行之前完成漏洞的检测;动态检测技术是指通过运行被测程序,检查运行结果与预期结果的差异并分析运行效率等性能。也就是说通过运行代码来检测代码的动态行为和运行结果的准确性。但一般来说,静态检测更加的方便快捷,无需执行程序,可在开发前期检测漏洞,因此缓冲区溢出漏洞的静态检测是测试者用得比较多的。但由于大多数静态分析工具建模不够精确,导致了缓冲区溢出漏洞检测的结果中存在较高的漏报率和误报率。在c和c++语言中,一些拷贝函数和常见的外部输入函数在分配内存和输入长度是容易产生缓冲区溢出。



技术实现要素:

本文发明了一种基于程序图的栈缓冲区溢出脆弱性检测方法。首先对源代码进行静态分析后构造相应的程序图。遍历生成的程序图寻找到危险函数,得到溢出点位置。并且通过比较函数操作的缓冲区空间与所要覆盖空间的大小计算地址的偏移。最后通过判断是否出现地址偏移而得到脆弱性检测的结果。

本发明的技术方案如下:

步骤1,对源代码进行静态分析后构造相应的程序图;

步骤2,遍历生成的程序图寻找到危险函数,得到溢出点位置;

步骤3,在溢出点比较函数操作的缓冲区空间与所要覆盖空间的大小计算地址的偏移;

步骤4,通过判断是否出现地址偏移而得到脆弱性检测的结果。

进一步方案,上述步骤1的具体步骤如下:

步骤1.1,对源代码进行控制流分析获得控制流信息和程序图有向边的信息,再对源代码进行数据流分析获得数据流信息和程序图节点的信息,推断代码中变量间的关系及实际特征;

步骤1.2,通过对源代码的控制流信息和数据流信息进行分析获取源代码中变量的初始化和被函数调用的信息,得到变量间的关系和变量与调用函数之间的关系;

步骤1.3,将变量的初始化和使用作为属性节点,按照控制流信息的顺序构造源代码的程序图。

进一步方案,上述步骤2的具体步骤如下:

步骤2.1,通过traversal方法遍历程序图,返回的节点是图中所有变量的初始化节点和变量被调用节点;

步骤2.2,使用toset方法将变量初始化节点和变量被调用节点转换成节点集合,该节点集合包含了所有的变量初始化的节点和函数使用变量的节点;

步骤2.3,在节点集合中提取出调用变量的函数与危险函数集合da比较得到源代码中存在的危险函数,得到溢出点位置。

进一步方案,上述步骤3的具体步骤如下:

步骤3.1,在溢出点位置找到变量的调用函数,通过与危险函数库的对比判断危险函数的类型。本发明主要说明“strncpy()”“memcpy()”和“gets()”三种危险函数的脆弱性检测方法;

步骤3.2,分析“strncpy()”“memcpy()”和“gets()”等危险函数类型的脆弱性成因。对于strncpy()和memcpy()函数,获取函数操作的缓冲区空间o和覆盖空间c,但对于gets()函数只需要获取函数的缓冲区空间o;

进一步方案,上述步骤4的具体步骤如下:

步骤4.1,对于strncpy函数,如果复制的长度n<o,则没有脆弱性。如果n>o且o<c,则存在脆弱性;

步骤4.2,对于memcpy函数,如果复制的长度n<o,则没有脆弱性。如果n<o且o<c,则存在脆弱性;

步骤4.3,对于gets函数,如果o=[0,∞],则存在脆弱性。

与现有技术相比,本发明的有益效果:

1、本发明提出了一种基于程序图的栈缓冲区溢出脆弱性检测方法,可以更好地适用于资源访问类软件脆弱性检测,提高检测效率。

2、在程序图的基础上提出了一个栈缓冲区溢出脆弱性检测方法,用于指导构建缓冲区溢出的脆弱性检测模型,使其能够更好地适用于缓冲区溢出脆弱性检测。

3、本发明有常见脆弱性的实例验证来证明此检测方法的准确性,目的是更加精准地检测到软件系统中的脆弱性,提高系统的安全性。

附图说明

图1一种基于程序图的栈缓冲区溢出脆弱性检测方法流程图

图2构造程序图流程图

图3寻找危险函数流程图

图4缓冲区空间与覆盖空间大小比较流程图

图5脆弱性判断流程图

图6根据代码构造的程序图

具体实施方式

为了更好地理解本发明一种基于程序图的栈缓冲区溢出脆弱性检测方法,下面结合附图和具体实施案例对本发明作进一步说明,须指出的是,所描述给出的实施案例旨在便于对本发明的理解,而对其没有任何限定要求。

本发明提出了一种基于程序图的栈缓冲区溢出脆弱性检测方法,可以更好地适用于资源访问类软件脆弱性检测,提高检测效率。

首先,定义本发明所涉及到的几个概念定义和计算公式如下。

定义1程序图:又称程序流程图,以图形的方式来表达代码的逻辑功能、数据在代码中的逻辑流向和逻辑变换的过程,是结构化系统分析方法用于表示代码的一种图示方法,是有向边和属性节点的集合。形如g=<v,λ>,v是程序图上属性节点的集合,λ是有向边的集合。

定义2危险函数:指一些危险的、使用时容易造成缓冲区溢出的函数如表1所示,主要存在于c/c++语言中。如一些拷贝函数strncpy()、memcpy()在分配内存空间时容易造成缓冲区的溢出,外部输入函数gets()在输入长度时经常会造成缓冲区的溢出。

表1

定义3危险函数集:da=<d,e>,其中d={d1,d2,d3,…,dm}是危险函数名集合,e={e1,e2,e3,…,em}是危险函数描述内容。

定义4图的遍历:是指从图中的任意节点出发,按照某种规则访问图中的所有节点,并且所有节点有且仅访问一遍。目前图遍历主要有深度优先遍历和广度优先遍历两种。深度优先遍历的思想是从图的某个节点出发,访问后选择一个与这个节点相邻且没有被访问过的节点访问,再从这个节点出发选择一个与它相邻且没有被访问的节点访问,以此类推继续直到所有节点都被访问到。广度优先遍历的基本思想是按层次的访问。

定义5traversal遍历:指图的深度优先向下遍历,返回的是节点的集合。形如:

traversall(x)=∪v∈x{t:(v,t)∈λandλ((v,t))=1},表示traversal遍历所返回的节点集合x中包含图的所有节点,t为节点的属性值。traversal1表示traversal遍历返回所有标签值为l的边。

定义6toset操作:将多个元素转换成以这些元素为集合的操作。

定义7strncpy函数:是c语言的库函数之一,来自c语言标准库。形如char*strncpy(char*dest,constchar*src,sizen),把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,返回的是dest。

定义8memcpy函数:是c语言的库函数之一,来自c语言标准库。形如char*memcpy(char*dest,constchar*src,sizen),把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,返回的是dest的指针。

定义9gets函数:是c语言的库函数之一,来自c语言标准库。功能是从输入缓冲区中读取一个字符串存储到字符指针变量str所指向的内存空间。

如图1所示,本发明的一种基于程序图的栈缓冲区溢出脆弱性检测方法流程图,包括:

步骤1,对源代码进行静态分析后构造相应的程序图。

上述步骤1中,参照图2,构造相应的程序图的步骤如下:

步骤1.1,对源代码进行控制流分析获得控制流信息和程序图有向边λ的信息,再对源代码进行数据流分析获得数据流信息和程序图节点v的信息,推断代码中变量间的关系及实际特征;

步骤1.2,通过对源代码的控制流信息和数据流信息进行分析获取源代码中变量的初始化和被函数调用的信息,提取源代码的控制流信息、指针变量、内存块、常量和函数结构等数据信息,并得到变量间的关系和变量与调用函数之间的关系;

步骤1.3,给源代码中的每一行代码进行编号,在确定完程序图的开始节点和终止节点后分析每一行代码明确每一个变量的初始化节点、变量的使用节点和有向边。将这些节点和有向边作为属性节点和属性边构建源代码的程序图。可以比较全面地展示出代码的语法结构具有较高的遍历效率。

步骤2,遍历生成的程序图寻找到危险函数,得到溢出点位置。

上述步骤2中,参照图3,寻找危险函数得到溢出点位置的步骤如下:

步骤2.1,通过traversal方法遍历程序图,返回的节点是图中所有变量的初始化节点和变量被调用节点。使用toset方法将变量初始化节点和变量被调用节点转换成节点集合,该节点集合包含了所有的变量初始化的节点和函数使用变量的节点;

步骤2.2,traversal遍历结合toset方法的规则如下:

其中用于遍历程序图获得到所有变量的初始化节点。同理用于遍历程序图获得到所有变量的使用即被调用的节点。最后结合toset方法所有变量的初始化节点和被调用节点集中转换成节点集合。

步骤2.3,在节点集合中提取出调用变量的函数与危险函数集合da比较得到源代码中存在的危险函数,得到溢出点位置。

上述步骤3中,参照图4,比较函数操作的缓冲区空间与覆盖空间大小的步骤如下:

步骤3.1,在溢出点位置找到变量的调用函数,通过与危险函数库的对比判断危险函数的类型。本发明主要说明“strncpy()”“memcpy()”和“gets()”三种危险函数的脆弱性检测方法,strncpy()、memcpy()等一些拷贝函数在分配内存空间时容易造成缓冲区的溢出,而外部输入函数gets()在输入长度时经常会造成缓冲区的溢出;

步骤3.2,对于strncpy函数,函数操作的缓存区空间operate(dest)=[p1,q1],覆盖空间covered(src)=[i1,j1],其中p1,q1分别是缓冲区空间的初始地址和终止地址,i1,j1分别是覆盖空间的初始地址和终止地址。对于memcpy函数,函数操作的缓存区空间operate(dest)=[p2,q2],覆盖空间covered(src)=[i2,j2],其中p2,q2分别是缓冲区空间的初始地址和终止地址,i2,j2分别是覆盖空间的初始地址和终止地址。对于gets函数,函数操作的缓存区空间operate(dest)=[p3,q3],其中p3,q3分别是缓冲区空间的初始地址和终止地址。

上述步骤4中,参照图5,脆弱性判断的步骤如下:

步骤4.1,对于strncpy函数,如果复制的长度n<p1-q1,则没有脆弱性。如果n>p1-q1且(p1-q1)<(i1-j1),则存在脆弱性;

步骤4.2,对于memcpy函数,如果复制的长度n<p2-q2,则没有脆弱性。如果n<p2-q2且(p2-q2)<(i2-j2),则存在脆弱性;

步骤4.3,对于gets函数,如果p3-q3=[0,∞],则存在脆弱性。

本发明分析给定的脆弱性代码,按照上面所描述的脆弱性检测方法进行脆弱性的验证。所要分析的代码如下所示。

(1)对上述所示代码进行分析后构造的程序图如图6所示;

(2)遍历图6所示程序图找到危险函数在代码的第6行;

(3)确定危险函数的类型是字符串类型中的memcpy,操作的缓存区空间o=12,覆盖空间c=6;

(4)n=5<o-c=6并且o>c,所有该代码没有缓冲区溢出的脆弱性。

上文所列出的一系列的详细说明仅仅是针对本发明的可行性实施方式的具体说明,它们并非用以限制本发明的保护范围,凡未脱离本发明技艺精神所作的等效实施方式或变更均应包含在本发明的保护范围之内。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1