(三)Static Analysis

2022/09/30

前言

关于Static Analysis得从编程语言(Programming Languages简称,PL)说起,PL作为软件的核心技术,在软件开发效率、软件可靠性、安全性、性能等方面都提供了根本性的支持。

PL学科庞大,结构复杂,在这里,我们将其分为三类:

  1. 纯PL,即关于PL本身的设计。例如,
  1. PL支持环境,即支撑PL的编译和运行系统。例如,
  1. PL应用,即利用PL的语法语义等知识对PL编写的程序展开的一系列应用。例如,

上述分类只是一个框架,实际上并没有展开,因为它很难展开,太庞杂了。大致了解一下就OK了,

Program Analysis

重要性

学术界

PL应用中最庞大、最火热的分支之一当然是程序分析了,程序分析可以看成是一个交叉的研究方向,造成这种交叉性质的原因不难理解:程序分析是一种方法技术,目的是分析出程序在可靠性、安全性、性能等各种方面的表现和问题,而各领域的程序都是用编程语言写的,且都或多或少地有上述方面的分析需求,因此不同领域对于程序分析的广泛兴趣便不足为奇。

企业界

当今的软件越来越复杂,在可靠性、安全性、性能等方面提出了新的要求和挑战,这些都是传统技术(如软件测试等)很难解决的,国际知名的大公司都有专门的程序分析研究或开发组,例如Microsoft,Google,Oracle,Apple,IBM,Facebook、Uber、华为等等。随着人们逐渐意识到程序分析的重要性,专门研发程序分析技术的公司也越来越多,例如Coverity(被收购),GrammaTech,Semmle,SourceBrella(源伞)等

什么是程序分析

程序分析是以某种语言书写的程序为对象,对其内部的运作流程进行分析,自动分析计算程序的正确性以及高效性等属性的过程。

程序分析技术可以大致分为两类。第一类是静态程序分析,即在不执行程序的情况下进行程序分析。第二类是动态程序分析,即通过运行程序或者在程序运行期间进行分析。当然,也有很多研究工作是关于如何有效结合静态和动态程序分析的。同时,因为通常无法拿到真正的程序正确性的需求,绝大多数的程序分析技术着重于分析通用的程序正确性需求,比如如果有断言的话,我们尽量分析断言会不会被违背,再比如分析是否存在整数或者缓存溢出,再或者检测指针相关的安全漏洞等。

当前程序分析的研究大致可以分为两个部分:一是关于程序分析技术本身,二是把程序分析技术运用到新的领域,

就程序分析技术本身而言,很多值得研究的问题不断有新的进展。

比如提供更好的语言和工具让程序员更容易的描述程序的正确性。这个方向最新的一个尝试可能是现在差不多算夭折了的 Move 语言[1](一个针对智慧合约的编程语言)。在 Move 的设计里,程序员需要通过 precondiction 和 postcondition 来描述程序的正确性要求。当然这个愿望很美好,具体效果我们可能永远没法知道了

再比如,对基于静态分析的工具,一个重要的问题就是如何减少假警报的。而对于动态分析而言,对应的问题就是如何减少漏报

除了把静态分析做的更精确,和把动态分析做的更完备,还有一个趋势,就是结合不同的程序分析技术取长补短。比如 hybrid fuzzing 的做法是,通过有效的结合符号执行与模糊测试来提高测试的覆盖率

程序分析技术也越来越被用来分析一些非传统的 “程序” 上,比如智慧合约和神经网络。

智慧合约,简单的理解就是基于区块链运行的,相对简单的程序。传统程序有的问题(比如各种安全漏洞)智慧合约基本都有。同时,智慧合约的正确性要求和设计又和传统程序有所不同,这样就需要我们针对智慧合约适配现有的程序分析。近期有很多把静态分析和动态分析技术移植到智慧合约的工作。

神经网络可以看作是一类不是基于逻辑的程序当然,和传统程序一样,神经网络也有各种各样的正确性问题(比如鲁棒性,没有后门,公平性等等)

说的有点多了,hhh,回到正题,静态分析(Static Analysis)

Static Analysis

Static Analysis指在不对program进行运行的情况下,对其行为进行分析,搞compiler的人用之于优化,搞安全的用于做taint analysis。如今,软件工程、系统和安全方向的很多程序分析都是利用基础的静态分析技术和结果,结合程序和问题的特点,进行更high-level的分析,比如查到更有趣的bug和安全漏洞,或更好的帮助优化或理解程序等等。

我目前的学习方向主要还是如何将Static Analysis应用于安全方向,比如SAST漏洞扫描工具等,至于怎么样优化算法,怎么样提高性能,交给大牛去做吧,他们发论文,我们拿来用。正是由于上面的原因,所以自己其实对Static Analysis的理解并不深入,所以如果其中有什么错误,欢迎大佬指正,感激!

而其中四个非常经典流行的Java静态分析框架:

  1. Soot (国际知名的通用型Java静态分析框架,加拿大和德国静态分析团队开发,23年历史)
  2. Wala(国际知名的通用型Java静态分析框架,IBM研究中心静态分析团队开发,16年历史)
  3. Doop(国际知名的Java指针分析框架,希腊大学静态分析团队开发,13年历史)
  4. SpotBugs(国际知名Java缺陷分析框架,前身Findbugs,美国马里兰大学、Google等团队开发,18年历史

而静态分析中最核心、最重要的一个分支(之一),也是大家经常在各种程序分析论文和程序分析工具的代码、文档和注释中看到的指针分析(pointer analysis),又名指向分析(points-to analysis)或别名分析(alias analysis)

Alias Analysis

什么是指针分析

指针分析并不是“分析指针”,如果不好理解,你可以用它的另一个名字“指向分析”来记,顾名思义,给定程序的任何变量或引用p,指向分析在compile-time(静态)回答p都可能指向哪些值。既然知道了p1和p2都指向什么,如果p1和p2的指向有交集,就说p1和p2互相alias(alias对很多sound的分析是必须的),因此指向分析也叫别名分析即alisas analysis。

指针分析的重要性

指针分析可以认为几乎是所有静态分析的基础,因为它可以被用来构建全局的程序控制流(Interprocedural control flow graph, ICFG)和方法调用图(call graph),且所有全局的程序静态分析都需要这些基本结构,与指针分析提供的指向信息和别名信息来构建自己更high-level的静态分析。

小结

这篇笔记也是自己也是看了很多大佬的文章总结的,在学习的过程中,不禁感叹知识的浩瀚,自己的渺小,看到很有鼓舞的一段话,与诸君共勉:

现在的很多学生都很浮躁,没有深入思考或塑造过自己的价值观,个人价值观被当前的社会价值取向所左右,甚至裹挟,其结果是丰厚的年薪和体面的工作是衡量其人生是否成功的唯二标准,为此不惜加班熬夜,在资本铺出的路上透支狂奔,貌似只有拥有了自己的房子才可以开始享有人生,貌似只有在周遭的环境中脱颖而出才能证明自己不虚此生,来不及看风景,来不及顾家人,仿佛生活没有给你留什么时间,却又花大量时间去惆怅为什么生活使你艰难向前。接下三句话也送给你们,希望你能“不要浮躁,认识自己,重拾自信”,希望你能找到自己的路,快乐向前。

不要浮躁

浮躁,往往来源于与旁人的比较,有意也好,无意也罢,是具有社会属性的我们难以避免的人之常情。然而,如果从比较中无法再获得正向激励,反而发现其开始对自信打击,使自我怀疑,我们就需要开始重新审视自己面对生活的态度了。

学不懂一门课程,就慢慢学,多会做一道题,多弄懂一个知识点,都比之前的自己更好了,就值得肯定;人生很长,不能因为毕业时没有优势就同时否认毕业几年后的自己,如果仅仅为此就放弃了当下的努力,桎梏不前,那理由再多也只不过是掩饰自己懒惰的借口。

这个世界的存在是唯物的,但是如何看待她的存在却是唯心的。不要再同旁人比较了,很多时候这一辈子这么累就是因为人生路上一直看着别人不看路才磕磕绊绊的。从当下浮躁的集体价值观中逃出来吧,心远地自偏,才能看清脚下的路,这路上实际上只有你,要比也只和自己比,如此,很多东西便会释然了。

认识自己

人生其实有一门课,就是不断地发掘自己,认识自己,看看什么事情可以让自己愿意花时间和精力去做,做的过程是快乐的,做完后是欣慰满足的。很多时候兴趣的养成,是靠因缘际遇碰到了,你花时间去做发现自己并不排斥,然后一路做下来,越来越专业,受到越来越多来自他人的正向反馈与自我的肯定,也就越来越愿意花时间去做,由此进入了正向的循环。但是需要注意的是,这个“因缘际遇”碰到的事情,不一定是你大学学的专业。

很多时候,我们被生活推着走,貌似18年的努力就是为了能上一个好大学,选择一个好专业。但是什么是好专业?大家眼中的好专业,就是好专业吗?现在的大学教育培养更多的是专业技能,缺失了很多能够让人自省、自察、自悟的人文关怀,社会的浮躁也多源于此,

这些对兴趣的专注和纯粹本应该是大学生在自己专业上该有的年轻的、百舸争流的样貌,如今却被年薪、房价和社会的物化价值观所左右。如果连我们国家顶尖大学的教育都摆脱不了物欲横流的浮躁,又如何完成国家民族集体人格的进一步塑造?

重拾自信

自信的时候不会多想,只想去做,只想做好。既然曾经拥有过,它就一直还在,也许你因曾经历的人或事将它埋在了心底,怯于外露,但它终究是属于你的。如果能“不浮躁”,如果开始做好“认识自己”的准备,就请把那份自信重拾起来,微笑着上路吧。

学习

自己在学习静态分析的过程中,主要的学习方向是,编译原理第二版(紫龙书)—>北大软件分析技术公开课—>南大软件分析公开课,接下来就是自己学习使用Soot,CodeQL等框架,后面也会记录一下自己的学习过程。

北大的软件分析公开课是熊英飞老师的,B站直接搜。

南大的软件分析公开课是谭添,李樾老师讲的,B站也直接搜

参考

The Move Language - The Move Book (move-book.com)

沉浸式《程序分析》教材 - 知乎 (zhihu.com)