Learning to Explore Paths for Symbolic Execution
CCS 2021年的一篇关于符号执行路径选择优化的论文。
简介
符号执行是很强力的技术,能够生成测试样例来让程序执行想要的路径。然而,符号执行的扩展性受限于路径爆炸问题。因此,要提高符号执行的有效性,就要让符号执行能够选择正确的符号状态。
文章提出了一种基于学习的技术,能够有效地选择合适的状态来缓解路径爆炸问题。learch能够直接估计每个状态对最大化覆盖率这一目标的贡献。而不是像传统的启发式方法基于简单的策略。而且,learch利用了现有的启发式方法来生成训练数据和提取特征。因此,learch从其他专家设计的启发式方法中受益颇多。
在klee中实现了learch,同时评估了许多真实程序,结果表明,learch是有效的:能够覆盖更多的代码,比现有的启发式方法或者启发式的组合能检测出更多的bug。同时,我们也发现利用learch生成的测试样例作为fuzz的初始种子能够找到更多的路径和bug。
看了摘要以后有几个比较感兴趣的问题:
- 什么叫做迭代式学习?
- 他是怎么生成数据集和提取特征的?
- 最后这个作为fuzz的初始种子的实验是怎么做的?
Motivation
文章阐述motivation的思路是:符号执行根本的问题(路径爆炸),现有的启发式方法无法解决。
路径爆炸体现在这张图,候选的符号执行状态非常的多。
现有启发式的局限体现在:没有任何的启发式方法要优于其他的启发式方法,每种启发式方法都覆盖了程序的各个部分,可以说是各有优缺点。组合起来的启发式方法效果不错。
基于组合启发式方法效果不错这一点,作者认为需要用一种学习的策略来有效地组合这几种启发式方法。
方法
文章的核心是使用机器学习的回归模型评估状态的对于最大化覆盖率这个目标的贡献值。基于这个模型,符号执行选择贡献值最大的状态。
文章采用的是迭代式学习策略,在每轮迭代中,用符号执行对训练程序跑一下。一开始使用不同的状态选择策略来生成一些测试样例。然后对每个已经探索过的状态,我们提取他的特征(包括启发式方法用到的那些特征),然后计算他们的reward,也就是前面提到的贡献值。
这就生成了监督的数据集并且俘获到了每个策略的行为。最后,再训练回归模型来让模型能够准确地对每个状态进行估计。
方法
符号执行的目标:在最短的时间达到最大的覆盖率
reward的计算:从state状态生成的测试样例的覆盖率除以在状态d的时间
标签是reward,计算方式是覆盖的行除以每个状态的时间。
设计的特征:
标记了五种安全违反:
- 整数溢出
- Oversized shift
- out-of-bounds array reads/writes
- pointer overflow
- null deference
实验结果
主要回答这么几个问题:
Can Learch cover more code than existing manual heuristics?
Can Learch discover more security violations?
Can Learch generate better initial seeds for fuzzing?
What is the impact of Learch’s design choices?
数据集选择:
- coreutils是许多符号执行工作评测的程序集
- 程序的输入格式各种各样,并且广泛应用在fuzz和符号执行这些工作里
对比的启发式方法:
- rss:random state search
- rps:random path search
- nurs cplint and nurs depth:non-uniform random search
- sgs:subpath-guide search
- portfolio
覆盖率
发现的安全违反
结合模糊测试的效果
影响(挖到的真实漏洞)
发现了46个潜在漏洞,并且13个被认定为是真的bug。
相关工作
主要提到了符号执行、混合测试和机器学习应用到程序分析的一些工作。因为这方面都有些了解了,这里就不再详细介绍了,感兴趣的可以去看论文。