智能化漏洞挖掘技术总结

全文基于《从自动化到智能化:软件漏洞挖掘技术进展》进行提炼、总结、修改。1.静态漏洞挖掘技术

1.1面向源代码

面向源代码的漏洞挖掘主要采用基于中间表示的分析和基于逻辑推理的分析技术。
基于中间表示的分析技术主要包括数据流分析、控制流分析、污点分析、符号执行等。Pixy采用了取值分析、污点分析、指针别名分析等静态分析技术实现对PHP源码中的SQL注入和跨站脚本等漏洞的检测。Prefix采用了静态符号执行技术模拟执行C/C++源码程序,并采用约束求解对程序中的部分路径进行检测。Melange采用数据流分析的框架,通过对程序进行数据流、控制流等复杂分析检测安全相关的漏洞,并支持对大型C/C++源码程序的分析。
基于逻辑推理的分析技术主要是指模型检测,如MOPS、BLAST、SLAM是典型的面向C程序的模型检测工具,其基本思路是将程序结构抽象为状态机(布尔程序),然后基于归纳的安全属性对状态机进行遍历,检测其中存在的漏洞。

1.2面向二进制

面向二进制程序的静态漏洞的挖掘技术由于缺少源代码中的结构化信息,面临着值集分析(vaule-set analysis,VSA)与控制流恢复不精确的问题。当前,二进制静态漏洞挖掘技术主要包括基于模式匹配和基于补丁比对的技术。
在基于模式匹配的漏洞挖掘技术方面,GUEB提出了二进制程序中UAF漏洞模式,首先抽象出二进制函数中的内存模型,然后采用VSA分析技术追踪堆分配和释放指令相关的操作变量,并基于此建立UAF模式。LoongChecker使用了称为半仿真的二进制静态漏洞挖掘技术。通过VSA分析和数据依赖分析(data dependence analysis,DDA)技术实现对变量地址的追踪和数据流依赖分析,并采用污点分析技术检测潜在的漏洞。Saluki使用了路径敏感和上下文敏感的数据依赖分析,并采用完备的逻辑系统推理检测程序中的漏洞。
在基于补丁比对的漏洞挖掘技术方面,PVDF以二进制漏洞程序(带有权限提升漏洞)和补丁作为输入,从比对中提取多维属性描述的漏洞语义信息,并应用于后续的模糊测试中。BinHunt通过对二进制程序和带补丁的二进制程序间的比对提取漏洞相关的语义信息。具体而言,就是把二进制程序翻译成中间表示,并在此基础上构建控制流图,基于控制流图对比程序间的差异,提取相关的约束,然后采用符号执行技术进行验证,以此找出补丁对应的漏洞。

2.动态漏洞挖掘技术

常用的动态漏洞挖掘技术包括模糊测试、符号执行等

2.1

模糊测试(fuzzing)是一种自动化或者半自动化的软件测试技术,通过构造随机的、非预期的畸形数据作为程序的输入,并监控程序执行过程中可能产生的异常,之后将这些异常作为分析的起点,确定漏洞的可利用性。根据程序内部结构分析的量级轻重程度分,模糊测试技术主要可以分为白盒、黑盒、灰盒模糊测试。其中,白盒模糊测试是在对被测试程程序内部结构、逻辑进行系统性分析的基础上进行测试;黑盒模糊测试把程序当成黑盒处理,不对程序内部进行分析;灰盒模糊测试介于黑盒和白盒模糊测试之间,在对程序进行轻量级分析的基础上进行测试。按样本生成方式划分,模糊测试的测试输入可分为基于变异和基于生成2种方式。其中,基于变异的模糊测试在修改已知测试输入的基础上生成新的测试用例,而基于生成的模糊测试则是直接在已知输入样本格式的基础上生成新的测试输入。
下面介绍基于变异的模糊测试、基于生成的模糊测试和其他优化策略。

2.1.1基于变异的模糊测试。

在基于变异的模糊测试方面,研究人员借助程序执行环境信息和程序分析技术,有导向性地辅助、引导模糊测试的变异,具有代表性的工作有AFL、VUzzer、Honggfuzz、libFuzzer、Steelix、T-Fuzz、AFLFast、AFLGo、Driller等。
AFL 官网:https://lcamtuf.coredump.cx/afl/
VUzzer 源码:https://github.com/vusec/vuzzer
Honggfuzz 源码:https://github.com/google/honggfuzz
libFuzzer 源码:https://github.com/Dor1s/libfuzzer-workshop.git
T-Fuzz 源码:https://github.com/HexHive/T-Fuzz
AFLFast 源码:https://github.com/mboehme/aflfast
AFLGo源码:https://github.com/aflgo/aflgo
Driller源码:https://github.com/shellphish/driller

2.1.1.1代码覆盖率制导。

AFL使用进化算法(evolutionary algorithms)生成测试输入,在正常输入的基础上,通过简单的反馈回路的方式评估测试输入的质量。AFL会保留任何能触发新路径的测试输入,并对其进行变异及检查能否触发崩溃。AFL通过哈希函数检测分支覆盖筛选种子的方式具有较高的误报率,其哈希位图(bitmap)只有64 kB大小,导致普遍存在哈希碰撞的情况,进而导致其分支覆盖统计存在漏报,进而影响种子筛选,间接影响了代码覆盖率的增长。CollFuzz采用静态控制流图信息作为辅助,并设计了能避免哈希碰撞的基本块ID分配策略,从而实现比AFL更精确的分支覆盖检测。

2.1.1.2污点分析辅助。

BuzzFuzz使用动态污点分析技术自动定位影响程序脆弱点的测试输入中的字段,然后保留其他语法部分内容,只对这些字段进行变异。这样既能通过语法检查,也能有针对性地进行变异,提高漏洞挖掘的效率。TaintScope使用污点分析技术推断程序中与校验和处理相关的代码,以此帮助模糊测试工具绕过校验和检查。

2.1.1.3符号执行制导。

Driller采用模糊测试和符号执行交替探索程序执行路径,解决模糊测试陷入代码覆盖率增长慢的情况,这样能引导模糊测试探索到程序更深层次的节点,也能直接避免符号执行可能带来的路径爆炸问题.不过基于符号执行增强的模糊测试技术仍然会受限于符号执行中的约束求解问题,符号执行的引入可能会弱化模糊测试本身的可扩展性。

2.1.1.4控制流和数据流信息制导。

VUzzer在“轻量级”的动、静态分析基础上提取了程序的控制流和数据流信息引导变异。具体而言,VUzzer先在静态控制流分析基础上计算基本块的权重,然后在动态执行时筛选权重更高即路径更深的执行路径对应的测试输入为种子文件,并用动态污点分析定位变异点。相比AFL、Driller,VUzzer有更好的种子筛选、路径探索策略以及污染点定位、变异策略,能定向引导探索更深的执行路径,并定点变异。

2.1.2基于生成的模糊测试。

基于生成的模糊测试主要基于模型或者语法生成能满足程序语法和语义检查的测试输入,常用于高度结构化的测试输入生成。

2.1.2.1基于模型的模糊测试。

Peach、Spike是典型的基于模型的模糊测试工具,通过对输入格式定制编写数据模型(data model)和状态模型(state model)的方式指定输入数据的类型和依赖关系, 并结合变异策略生成测试输入。其中Peach通过编写配置文件实现对样本格式的约束,而Spike需要利用提供的编程接口来对样本格式进行约束。Pham等结合输入模型和符号执行技术生成测试输入,使用符号执行鉴别输入格式约束能有效保证输入的合法性。
Peach官网:https://www.peach.tech/

2.1.2.2基于语法的模糊测试。

CSmith根据C语言语法生成C程序源码,实现对C编译器的模糊测试。在C源码生成方面,CSmith随机选取符合生成规则和语法规则的C程序,这种方法能避免因未定义和未声明而导致编译报错的情况出现。LangFuzz基于语法学习测试集中的代码片段,并进行片段重组生成新的测试输入。在测试输入集选择上,LangFuzz假设基于问题测试集重组生成的测试输入比随机收集的测试输入更有可能触发程序缺陷。IFuzzer使用上下文无关的语言语法作为输入,并使用语法生成解析树,然后从测试集中抽取代码片段,并使用遗传进化算法对代码片段重组生成新的测试输入。Jsfunfuzz使用了历史漏洞知识和硬编码规则生成测试输入,以Mozilla浏览器中的Javascript解释器为测试目标,发现了1 800多个缺陷。Dewey等使用了称为约束逻辑编程(constraint logic programming, CLP)的技术生成测试输入。通过指定句法特征和语义行为,CLP能生成满足语法和语义合法性的测试输入。
CSmith 官网:https://embed.cs.utah.edu/csmith/
lFuzzer源码:https://github.com/vspandan/IFuzzer
Jsfunfuzz 源码:https://github.com/MozillaSecurity/funfuzz/tree/master/src/funfuzz/js/jsfunfuzz

2.1.2.3 其他优化策略。

除了上述进展外,还有一些重要研究侧重于种子筛选策略优化和调度策略优化。Rebert等把种子筛选问题转化成整数线性规划问题,并以挖掘更多漏洞为目标提出了多种种子筛选策略。AFLFast采用了把模糊测试问题建模为Markov模型,并采用特定的策略引导AFL优先选择低频路径和变异频率较低的文件作为种子文件进行变异,以此在相同的测试时间内探索更多的路径。AFLGo采用了模拟退火(simulated annealing,SA)算法对能逼近特定目标位置的测试输入分配更高的能量,并优先选取高能量种子文件进行变异。AFLGo的实验结果表明,这种导向型灰盒模糊测试(directed greybox fuzzing,DFG)比符号执行引导的白盒模糊测试和非导向型模糊测试具有更好的性能、更高的代码覆盖率并可挖掘出更多的漏洞。

2.2

符号执行
代表性工具有SAGE、S2E、Mayhem、KLEE、Triton、angr等。
S2E源码:https://github.com/S2E
KLEE 官网:https://klee.github.io/
Triton源码:https://github.com/JonathanSalwan/Triton
Angr 源码:https://github.com/angr/angr
符号执行需要解决几个问题

2.2.1路径爆炸问题,解决方案:

2.2.1.1启发式搜索(search heuristics)

这是一种以特定目标优先的路径搜索策略。
符号执行过程中对路径的探索可以看成是对符号执行树的探索,在执行树中,从根节点到叶子节点的一条路径代表程序实际执行中的一条路径,而其中的分支节点则表示程序实际执行中的分支条件。大部分启发式技术都专注于避免因陷入某部分相似路径而导致代码覆盖率低增长的情况,以期获得更高的代码和路径覆盖。KLEE中提出结合随机路径选择(random path selection)和覆盖优化搜索(coverage-optimized search)的混合搜索算法,2种路径选择方法交叉使用探索执行路径既能达到高代码覆盖率的目的,又能防止某种算法陷入困境导致路径探索无法进行。Ma等提出了以指定行代码可达性(line reachability)为目标的搜索策略。以程序中某行或多行代码为目标,找出能够驱动程序执行这些代码的实际输入问题称为代码行可达性问题。Godefroid等提出了代搜索(generational search)算法,在每一代新生成的路径约束中,对所有分支条件取反,然后能选择覆盖新代码块最多的测试输入作为新的种子输入。
状态空间简化通过相似路径合并、冗余路径删减的方式达到减少路径探测的目的。

2.2.1.2利用程序分析和软件验证等技术减少精简路径的措施来缓解路径爆炸问题。

Godefroid等采用了函数摘要的方式,对重用的函数提取约束组合(摘要),实现对函数路径的组合执行,避免了多次重复符号执行带来的开销。Ramos等提出的限定约束的符号执行(under-constrainted symbolic execution)采用了直接面向独立函数的符号执行技术,此技术限定了符号执行的范围,用精确度换取可扩展性的方式来提升符号执行的性能。Veritesting采用了静态符号执行技术增强动态符号执行技术,实现路径合并和冗余路径删减。Boonstoppel等提出了RWSet,从状态变量的相似性鉴别冗余性,如果当前状态的变量跟之前的路径变量一样,则会停止对当前状态的探索。

2.2.2约束求解问题。

约束求解问题是动态符号执行遇到的另一个瓶颈问题。在动态符号执行中,对路径约束条件可达性的判定以及相应测试输入生成都需要频繁地调用SMT求解器进行求解;而约束求解本身又是一个NP完全(NP-complete)问题,在最差的情况下求解NP完全问题的复杂度为指数级。频繁调用加上高的求解难度直接导致约束求解消耗了符号执行系统中的大部分资源。当前约束求解问题可以归结为求解能力和求解效率问题。
求解能力问题是指当前求解器对复杂约束条件处理能力的不足。例如对于浮点数运算、非线性运算等一些复杂运算的约束,求解器都不能很好地处理。
求解效率问题是指对于含有大量的约束条件的路径约束,求解器的性能会随着约束条件数量的增长而逐渐下降。这使得符号执行对大型程序进行分析时整体性能下降,从而影响其可扩展性。
针对约束求解的两大问题,研究人员提出了很多约束求解性能优化措施,主要可分为内部优化和外部优化。
解决方案:

2.2.2.1

求解器内部优化是指通过优化求解器本身对约束条件处理能力和效率来提高符号执行的性能,虽然近年来这方面的研究已经取得了比较大的突破,但仍然严重依赖于可满足模理论以及NP完全问题的研究进展。

2.2.2.2

求解器外部优化主要是指在调用约束求解器对路径约束求解之前的优化,是通过减少甚至避免符号查询的工作来增加符号执行性能的措施。例如,CUTE和KLEE采用了如表达式重写、符号值的实际替换、不相关约束的删除以及约束缓存等一系列措施,对路径约束进行精简和结果重用。而近年来在这方面的研究又有了不小的突破,包括Green、Recal、GeenTrie、Memoise等,这些工具的提出主要侧重于解决优化符号执行结果切分、标准化命名、约束式逻辑转化、求解结果的缓存、搜索和重用的效率问题。有关这些工具的实验结果表明:路径约束的精简能减轻约束求解的负担,而约束求解结果的缓存和重复使用能在同一程序的不同路径以及不同程序的不同路径间的约束求解问题上极大地减少对求解器的调用。

3.漏洞可利用性分析

3.1漏洞可利用性判定

该方面,现有的一些工具如!exploitable、gdb-exploitable、ASan等,已经可以对漏洞挖掘过程中的异常或崩溃的可利用性进行初步分类。例如,!exploitable对崩溃按可利用(exploitable)、高可利用(probably exploitable)、不可利用(probably not exploitable)、未知(unknown)进行评级划分,并提供了哈希去重功能。但上述工具具有误报率高的缺陷,实际验证的时候仍然需要具有丰富漏洞挖掘和分析经验的专家进行手工逆向分析、调试进行审核确认,并编写利用漏洞的验证程序。在崩溃样本量较大时,这种方式低效而且对分析人员具有较高要求。

3.2自动化漏洞利用生成

该方面,有代表性的相关工作如下图所示:
在这里插入图片描述

在2008年的IEEE S&P会议上,D.Brumley等人首次提出了基于二进制补丁比较的漏洞利用自动生成方法APEG。其核心思路是基于以下的假设条件,即补丁程序中增加了对触发原程序崩溃的过滤条件。因此,只要能够找到补丁程序中添加过滤条件的位置,同时构造不满足过滤条件的“违规”输入,即可认为是原始程序的一个可利用的输入候选项。根据其具体介绍内容可知,该工作主要分为三个步骤:首先,利用二进制差异比较工具(例如BinDiff与EBDS等)找到补丁存在的位置,即补丁程序的检测点;其次,找出不满足补丁程序检测点的输入数据作为原始程序的利用候选项;最后,利用污点传播等监控方法筛选所有能够对原始程序造成溢出或者控制流劫持等崩溃发生的有效利用
2011年的NDSS会议上,T.Avgerinos等人首次提出了一种有效的漏洞自动挖掘和利用方法AEG。该方法的核心思想是借助程序验证技术找出能够满足使得程序进入非安全状态且可被利用的输入,其中非安全状态包括内存越界写、恶意的格式化字符串等,可被利用主要是指程序的EIP被任意操纵。其具体流程为:首先,在预处理阶段,利用GNU C编译器构建二进制程序以及通过LLVM生成所需的字节码信息;其次,在实际分析的过程中,AEG首先通过源码分析以及符号执行找出存在错误的位置,并通过路径约束条件生成相应的输入;之后,AEG利用动态分析方法提取程序运行时的各类信息,例如栈上脆弱缓冲区的地址、脆弱函数的返回地址以及在漏洞触发之前的其他环境数据等;随后,综合漏洞利用约束条件以及动态运行时环境信息,最终构建可利用样本。AEG集成了优化后的符号执行和动态指令插装技术,实现了从软件漏洞自动挖掘到软件漏洞自动利用的整个过程,并且生成的利用样本直接具备控制流劫持能力,是第一个真正意义上的面向控制流漏洞利用的自动化构建方案。
为了摆脱对源代码的依赖以及保证系统适用场景的广泛性,S.K.Cha等人在2012年的IEEE S&P会议上提出了基于二进制程序的漏洞利用自动生成方法Mayhem。该方法通过综合利用在线式符号执行的速度优势和离线式符号执行的内存低消耗特点,并通过基于索引的内存模型构建,进而实现较为实用化的漏洞挖掘与利用自动生成方法。其具体流程如下:首先,通过构建两个并行的符号执行子系统,具体执行和符号执行子系统;其次,对于具体执行子系统,通过引入污点传播技术,寻找程序执行过程中,由用户输入所能控制的所有jmp指令或者call指令,并将其作为bug候选项交给符号执行子系统;之后,符号执行系统将所有接收到的污点指令转化为中间指令,并进行执行路径约束构建和可利用约束构建;最后,符号执行系统通过约束求解器来寻找满足路径可达条件和漏洞可利用条件的利用样本
由于高质量、多样性的漏洞利用样本对漏洞危害评估具有重要的意义,因此在2013年SecureComm会议上,M.H.Wang等人针对控制流劫持类漏洞提出了一套多样性利用样本自动生成方法PolyAEG。该方法的核心思想是通过动态污点分析找出程序所有控制流劫持点,通过构建不同的控制流转移模式完成漏洞利用样本的多样性构造。其具体流程为:首先,通过扩展硬件虚拟化平台QEMU实现程序动态监控并提取程序执行的相关信息;其次,在动态获取信息的基础上构建指令级污点传播流图iTPG以及全局污点状态记录GTSR,并以此为基础获取程序中所有可能的控制流劫持点、可利用的跳板指令以及可存放攻击代码的污点内存区域等内容;最后,通过构建不同的跳转指令链以及不同污点内存区域的攻击代码,并通过路径约束条件求解生成具有多样性的利用样本集合
为了解决数据执行保护和地址随机化给控制流劫持类漏洞利用带来的困扰,在2011年的USENIX Security会议上,E.J.Schwartz等人实现了一套面向高可靠性漏洞利用的ROP代码自动生成方法Q。其核心思想是收集目标程序中的Gadget并通过面向Gadget的编程语言自动构建ROP。具体的流程主要如下:首先,向Q提供未随机化的脆弱程序或者其他二进制库,并由Q找出具备特定功能的Gadget集合;其次,利用Q提供的编程语言QooL实现满足特定语义功能的目标代码,并通过Q将目标代码编译为面向Gadget的指令序列;随后,通过利用已获取的Gadget集合填充上一步得到的指令序列,从而形成最终的ROP代码
在数据执行保护、地址随机化以及控制流完整性防护手段大范围部署的情况下,大多数攻击者已经从面向控制流劫持的漏洞利用攻击转向面向数据流利用的攻击。正是在这样的背景下,H.Hu等人在2015年USENIX Security会议上首次提出了一种面向数据流利用的自动化构造方法FlowStitch。该方法的核心思想是在不改变程序控制流的前提下,利用已知的内存错误直接或者间接篡改程序原有数据流中关键位置上的变量,进而完成利用的自动化构造。根据文章介绍,其具体过程分为以下几个步骤:首先,以含有内存错误的程序、触发内存错误的输入以及特殊的正常输入作为整个自动利用系统的三个前提条件,其中“特殊的正常输入”是指在程序错误发生之前,其执行路径必须和触发内存错误的执行路径相同;其次,分别以错误输入和正常输入获取其对应的错误执行记录和正常执行记录,并以此为基础分别进一步提取内存错误影响的范围以及正常数据流中的敏感数据;最后,通过比对错误执行记录和正常执行记录的方式确定内存错误影响范围中可能涉及到的敏感数据,最终筛选所有可能被篡改的敏感数据并完成面向数据流的利用自动化构建过程。FlowStich是第一个面向数据流的漏洞自动利用方案,尽管其构造的利用样本无法直接运行任意的恶意代码,但由于可以泄露目标主机上的敏感数据,因此仍然具有很强的实用价值

4.AI赋能

近年来已经有智能化漏洞挖掘技术研究基于机器学习、深度学习技术展开,如下表所示。从应用场景看,涉及了二进制程序函数识别、函数相似性检测、测试输入生成、测试输入筛选、路径约束求解等领域;从使用的机器学习算法看,这些工作中分别采用了逻辑回归、随机森林、长短时记忆网络(LSTM)、强化学习等多种机器学习、深度学习的算法;从发表年份看,这方面的研究成果从2014年开始发表在信息安全顶级会议上,自2017年以来其数量逐渐上升,并已经成为当前信息安全研究领域的热点。
在这里插入图片描述

4.1二进制程序函数识别

二进制程序函数识别是二进制分析的基础,对于软件漏洞分析与修复,甚至恶意软件检测、协议逆向等都至关重要。由于二进制代码缺少高级语言程序中的信息,函数的识别往往比较困难,现有的反汇编分析工具具有识别正确率低的缺陷。Bao等提出了ByteWeight方案,采用机器学习算法实现对二进制程序函数的识别。具体而言,首先采用加权前缀树(weighted prefix tree)学习函数的签名,并通过签名匹配二进制片段的方式识别函数。其中,树中每个节点与二进制中的字节或指令相对应,而从根节点到某个既定节点的路径代表了可能的字节或指令序列,权重则表示了对数据集采用简单线性扫描算法学习到的字节或指令序列的置信度。在鉴别函数的同时,ByteWeight采用值集分析(value set analysis, VSA)和增量控制流恢复算法实现对函数边界的识别。此种方案可以获得比IDA Pro和BAP工具更高的准确率。Shin等用循环神经网络算法改进了ByteWeight的性能,在模型训练时间上有了数量级上的提升,并取得了更高的准确率。

4.2函数相似性检测

现代应用程序中,直接调用第三方函数可以节约开发成本、提高开发效率,是被广泛接受的开发惯例。但这种方式容易导致供应链安全风险,一旦被调用函数存在漏洞,则调用这一函数的程序也可能存在漏洞。通过函数相似性检测技术可以实现对不同程序间的同源性漏洞的检测,但当前基于图的相似度匹配的方法具有计算量大、准确率低的缺陷。Xu等提出了Gemini方案,Gemini把函数控制流图CFG简化为带节点属性(数字特征)的控制流图(ACFG),然后用Structure2vec算法转化为数字向量,使用Siamese网络架构训练,实现相似的函数距离近的目标,最后通过计算函数向量距离实现函数相似性的检测。Gemini能应用到跨平台的二进制函数相似性检测,并取得了比其他基于图相似性匹配的工具(如Genius更高的准确率和检测效率。

4.3测试输入生成

在软件漏洞挖掘中,构造代码覆盖率高或脆弱性导向型的测试输入能提高漏洞挖掘的效率和针对性。利用机器学习技术可以对海量测试样本进行分析、学习,并利用生成模型指导生成更高质量的测试输入样本。Godefroid等首次把模糊测试中的高结构化样本生成问题转换成了NLP领域的文本生成问题,采用了Char-RNN(recurrent neural network)模型实现对PDF文件格式中的obj语法的学习,并用训练好的模型生成具有多样性的obj对象和PDF文件。She等提出了采用深度神经网络指导模糊测试输入生成的方案Neuzz。Neuzz采用了CNN(convolutional neural network)学习连续可微的神经程序(neural program),用来近似模拟目标程序中的实际逻辑,然后通过对学习好的神经程序求梯度的方式指导测试输入生成,以此取得对目标程序更高的分支覆盖。与AFL相比,Neuzz在6个不同的常用程序中多发现了70倍的分支,并多发现了36个缺陷。Bottinger等提出了深度强化学习增强的模糊测试技术,借助Markov模型把模糊测试问题转化成强化学习问题,并利用Q-learning算法优化预定义的奖励函数。实验结果表明,使用深度强化学习增强的模糊测试技术比随机变异能取得更高的代码覆盖率。Nichols等提出了生成对抗网络(GAN)增强模糊测试技术。该方案不依赖于大数据量的样本训练,并能比AFL的随机变异和基于LSTM模型引导的变异更高效地发现更多的路径。
neuzz源码:https://github.com/Dongdongshe/neuzz

4.4测试输入筛选

测试样本筛选的目的是从海量样本中选择更有可能触发新路径或触发漏洞的测试输入。使用机器学习技术通过对大量的测试样本进行处理,从而决定哪些应该被进一步分析,尽可能准确地对样本进行标记,然后再用于寻找安全漏洞。Rajpal等使用LSTM、序列到序列(Seq2seq)等神经网络学习模糊测试过程中的历史变异样本及代码覆盖率等数据,训练出能指导对输入文件进行定向变异的模型。此外,Spieker还提出了采用强化学习的算法优先筛选漏洞导向型的测试用例,应用在持续集成(continuous integration, CI)及回归测试(regression test)中。

4.5路径约束求解

模糊测试,特别是代码覆盖率制导的模糊测试(如AFL),侧重于筛选可以覆盖新路径的样本为种子文件,但对种子文件变异时并没有充分利用程序数据流等信息指导变异,这使得变异盲目低效,生成样本冗余。现有的一些启发式优化工作如Steelix能够对魔术字节跟踪定位,但无法对其他路径约束求解。具备路径约束求解能力是符号执行比模糊测试等漏洞挖掘技术更先进的体现,也使得符号执行在理论上具备了系统性探索程序执行路径的能力。但复杂程序中的路径爆炸问题带来的对SMT求解器的频繁调用,以及SMT求解器本身的能力和效率的不足,使得约束求解占用了符号执行中主要的性能开销,约束求解问题也成为符号执行中面临的主要瓶颈问题之一。Angora采用污点追踪测试输入中影响条件分支的字节,然后使用梯度下降的方式对变异后生成的路径约束进行求解。这种方式避免了符号执行调用SMT求解器可能带来的开销以及复杂约束不可解的问题,但梯度下降对目标函数不可导或存在不可导点时,仍然会出现求解困难的问题。
Angora 源码:https://github.com/AngoraFuzzer/Angora

4.6漏洞程序筛选

传统的漏洞挖掘技术如模糊测试、符号执行等已经成功地从各类软件中发现了大量的漏洞,但当被测试程序复杂且数量庞大的时候,使用这些技术挖掘漏洞显得效率低下。VDiscover采用机器学习技术从大量的程序中快速筛选更有可能带有漏洞的程序。具体而言,VDiscover收集程序中的标准C库函数调用序列及其参数的动态值作为静态和动态特征,并对其做标注,然后采用带监督的机器学习算法(如随机森林,逻辑回归等)训练模型,当有新的被测试程序需要分类的时候,训练好的模型可以直接对提取的相应特征进行预判和标注。
VDiscover首次验证了采用机器学习技术筛选漏洞程序的可行性,但其采用人工定义和提取特征的方法具有较大的局限性。漏洞成因复杂,VDiscover提取的程序静态特征和动态特征并不能精确地表征各种类型的漏洞, 这可能造成较高的误报和漏报。另外,采用机器学习直接对漏洞程序进行预测的方式无法生成测试用例来动态验证漏洞。
vDiscover官网http://www.vdiscover.org

4.7源代码漏洞点预测

传统静态漏洞挖掘技术中,依赖于人工定义漏洞模式的检测方式经常会导致较高的漏报率。LiZhen提出了VulDeePecker方案,采用BLSTM算法对C/C++源代码中的漏洞点进行预测。鉴于传统的漏洞分类过细导致难以抽象提取为特征的问题,其设计了能覆盖多种漏洞类型的特征,这种方式不以函数为粒度,只考虑数据流保留语义上关联的代码行作为代码小部件(code gadgets)对程序进行表征,然后转换成向量作为深度学习的输入。但VulDeePecker方案中,代码小部件转换成向量的过程存在较大的信息丢失问题;另外,该方案只支持对缓冲区溢出和资源管理相关的漏洞的检测。
Vuldeepecker:https://arxiv.org/pdf/1801.01681.pdf
Vuldeelocator:https://deepai.org/publication/vuldeelocator-a-deep-learning-based-fine-grained-vulnerability-detector

补充

1.污点分析

污点分析是一种跟踪并分析污点信息在程序中流动的技术,其分析对象是污点信息流。污点指的是受到污染的信息。在程序分析中,将来自程序之外并且进入程序的信息当做污点信息,。根据分析的需要,程序内部使用的数据也可作为污点信息,并分析其对应的信息的流向。根据污点分析时是否运行程序,可以将其分为静态污点分析和动态污点分析。
污点分析的过程包括:识别污点信息在程序中的产生点并对污点信息进行标记;利用特定的规则跟踪分析污点信息在程序中的传播过程;在一些关键的程序点检查关键的操作是否会受到污点信息的影响。污点信息的产生点称为source点,污点信息的检查点称为sink点。
以下图为例来说明污点分析过程
在这里插入图片描述

将scanf所在的程序点作为source点,将通过scanf接收的用户输入数据标记为污点信息,并且认为存放它的变量x是被污染的。如果在污点传播规则中规定“如果二元操作的操作数是污染的,那么二元操作的结果也是污染的”,则对于y=x+k,由于x是污染的,因此y也被认为是污染的。一个被污染的变量如果被赋值为一个常数,它将被认为是未污染的。对于x=0,将x从污染状态转变为未污染。对于while(i<y),这句所在的程序点在这里被认为是一个sink点,如果污点分析规则规定“循环的次数不能受程序输入的控制”,那么在这里就需要检查变量y是否是被污染的。
污点分析代表性工具有:
TainkCheck http://bitblaze.cs.berkeley.edu/papers/taintcheck-full.pdf(2004年的工作,作者之一是“互联网安全教母”Dawn Song,也是清华张超老师在伯克利做博士后时的合作导师),没找到源码
Flayer https://www.usenix.org/legacy/events/woot07/tech/full_papers/drewry/drewry.pdf,源码:https://code.google.com/archive/p/flayer/

2.符号执行

符号执行是一种用符号值代替数字值执行程序的技术,符号是表示一个取值集合的记号。使用符号执行分析程序时,对于某个表示程序输入的变量,通常使用一个符号表示它的取值,这个符号可以表示程序在此处接收的所有可能的输入。此外,在符号执行的分析过程中那些不易或者无法确定取值的变量也常常使用符号表示的方式进行分析。
符号执行的分析过程大致如下:首先将程序中的一些需要关注但是又不能直接确定其取值的变量用符号表示其取值,然后通过逐步分析程序可能的执行流程,将程序中变量的取值表示为符号和常量的计算表达式。程序的正常执行和符号执行的主要去呗是:正常执行时程序中的变量可以看做被赋予了具体的值,而符号执行时,变量的值既可以是具体的值也可以是符号和常量的运算表达式。
以下图的符号执行源代码为例,函数中的参数x,y分别用符号a,b表示
在这里插入图片描述

基于上图的代码可以得到下图所示的程序流程图
在这里插入图片描述

可以看到共有三条执行路径,每条路径都对应着一个路径约束(path constrain,PC)。其中返回true的路径有一条,带入符号后,对应的路径约束为a>60&(b2)==128;返回false的路径有两条,对应的路径约束为a<=60|(a>60&(b2)!=128)
这个例子表明,使用符号执行技术分析程序,对于分析过程中遇到的程序中带有条件的控制转移语句(条件分支语句、循环语句等),可以利用变量的符号表达式将控制转移语句中的条件转化为对符号取值的约束,通过分析约束是否可以满足,判断程序的哪条路径是可行的。这一部分是符号执行分析的关键部分。由此将判断路径条件是否可满足的问题转化为判断符号取值的约束是否可满足的问题。而对于约束是否可满足的判断,通常使用约束求解的方法,该过程由约束求解器完成(约束求解器是对特定形式的约束表示进行求解的工具)。在符号执行的分析过程中,常使用可满足性模理论(satisfiabilti modulo therries,SMT)求解器对约束进行求解,为此需要将符号取值约束的求解问题转为SMT问题,即一阶逻辑的可满足性判断问题。
常用的SMT求解器有
STP http://people.csail.mit.edu/vganesh/STP_files/stp.html 源码:https://stp.github.io/
Z3 https://link.springer.com/chapter/10.1007/978-3-540-78800-3_24 源码:https://github.com/Z3Prover/z3

3.插桩

插桩技术是将额外的代码注入程序中以收集运行时的信息,可分为两种:
源代码插桩(Source Code Instrumentation(SCI)):额外代码注入到程序源代码中。
原始程序:
在这里插入图片描述

插桩后的程序
在这里插入图片描述

二进制插桩(Binary Instrumentation(BI)):额外代码注入到二进制可执行文件中。
静态二进制插桩:在程序执行前插入额外的代码和数据,生成一个永久改变的可执行文件。
动态二进制插桩:在程序运行时实时地插入额外代码和数据,对可执行文件没有任何永久改变。
目前,应用广泛的动态二进制分析工具有
Pin 源码:https://software.intel.com/en-us/articles/pin-a-binary-instrumentation-tool-downloads
DynamoRIO 官网:https://dynamorio.org/
Frida 官网:https://frida.re/
Valgrind 官网:valgrind.org

  • 4
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值