探索程序分析:以静态单赋值(SSA)格式为基础的YakSSA
2024-5-10 16:18:26 Author: mp.weixin.qq.com(查看原文) 阅读量:3 收藏

数据流分析是什么

在程序分析之前,我们从数据流开始谈起。

首先来看这段代码:

var a = func1()var c = 1c += avar target = func2(c)

在这段代码中,我们提出以下两个问题:

  • target 受到哪些变量的影响呢?

答案应该是c, 如果更加准确一些,应该要考虑到c +=a这样的语句,那么答案是c,a。

  • target 受到哪些值的影响呢?

答案应该是:func1,1,func2  这两个值,获得这样的答案应该是没问题的吧,

在我们读出这样的信息的时候,其实是在下意识的追踪入到func2的这个c数据流

ok,我们来讨论两个问题:

YAK

1、传入到func2的这个c,是指什么?

在原本的代码中,c这个变量:

  • 两处赋值的位置,分别为:c = 1, c = c+a

  • 有两处使用的位置,分别为:c = c + a, sink(c)

对于数值来说:c这个变量中保存了两个数值:

  • 数值:1, 这个值赋值给了c,然后在c = c + a的时候被使用。

  • 数值1+a, 这个值通过c = c(1) + a赋值给了c, 在func2(c)的时候被使用。

我们将两个不同值的变量c通过后缀进行区分,于是我们得到这样的代码:

var a = func1()var c1 = 1c2 = c1 +  avar target = func2(c2)

此时,我们可以简单地解释,什么是传入到func2中的c,也就是c2。

YAK

2、数据流是什么

基于上面的这个例子,我们发现通过将重新赋值的变量拆分,我们可以直接让每一个变量都表示单独的一个值,那么进一步,为什么还需要变量呢?

如果去掉变量仅仅保留值之间的关系,我们将会得到以下这张图:

可以看到,这张图里,每一个节点都是值,函数本身是一个值,像这里的函数f和函数func1、func2,常量、运算、函数调用都是值。

数据流是通过有向图的形式表达值之间的使用和被使用的关系。

在这里呢,我们隐去了很多编译相关的前置知识,用这样一个例子展示了下数据流和基于数据流的程序分析,这其实是非常符合我们在分析一段代码时的逻辑的。

在编译领域的程序分析

首先 编译过程的概述图如下:

值得注意的有两点:

  • 多前端,通过统一的中间表示抽象出来编译中端,将多种前端进行整合,并将可通用的分析方案在编译中端进行。

  • 中端的多层级表示:中间代码表示一般会采用多种设计,从高级到低级会一层层转换,并在每一层都进行分析,最后通过最后一级最低的IR产生可执行代码。

在编译领域中,经常进行的分析有以下三种:

  • 基于抽象语法树(AST)的分析:

    • 优点:和源码关系密切,可以非常细节地和源码相对应

    • 缺点:难以进行有效的数据流分析

  • 基于三地址码形式的中间代码表示

    • 优点:产生非常简单,并且和机器码类似,可以进行针对不同后端的机器码的优化。

    • 缺点:仍然没有办法直接分析数据流,而且相对于AST距离源码也有较大的差距

  • 基于静态单赋值格式(SSA)的中间代码表示(IR)

    • 优点:该指令的设计上就直接引出了使用-被使用的值的关系,天然可以进行数据流分析。

    • 缺点:缺少对于变量、作用域相关的处理

编译领域程序分析的总览:

在安全领域的程序分析

在安全领域的程序分析,在程序分析本身的要求上,应该有以下一些需求:

YAK

现状:

在现有的工具中,我们可以了解到:

  1. soot的传统数据流分析不能直接通过数据流图进行分析,并且这套方案维护复杂,很多基于soot的工具也只能在此基础上增加规则而非修改数据流分析方案。

  2. CodeQL的用户接口设计优秀,但基于AST的方案导致不同的语言API和分析方案基本都是特化的,甚至某些概念在不同语言中结构都不一致。

对于安全领域程序分析的一些探索:

需要一个强大的基于图的数据流分析方案,同时尽量保证其通用性,在不同语言中只需要前端接入,即可实现分析能力。

基于图的SSA格式IR的分析:这是各种编译器内部已经做的,从SSA这个概念提出、到LLVM中大量的使用、再到目前的绝大多数编译器都会保留这一设计,甚至目前的很多编译器中端设计中尽力保持SSA格式贯穿分析过程,这一分析思路已经在编译领域反复验证。

但同时,多语言的抽象和统一问题,传统SSA设计上的太过于底层以及内存操作指令 都导致在安全领域的实践中存在较大的差距。

YakSSA HIR

YakSSA的使用如下:通过简单的API即可进行:

  • ssaapi.Parse 进行程序的解析

  • 通过prog.Ref进行在数据流图上某个值的提取

  • 通过GetTopDefs进行对于该值的数据流分析。

可以看到在这一个例子中,和我们文章开头的例子一致,得到了一致的结果。

在以下的例子中,可以看到YakSSA在过程内的分析能力:

分析Yaklang语言,跨过程分析演示:

分析Java语言,左侧是代码,右侧是YakSSA测试以及结果,可以看到类之间的跨过程分析能力:

分析Java语言,跨越类对类成员的访问能力:

这是一个反例,可以发现对类成员的追踪的精准性。

END

  YAK官方资源 

Yak 语言官方教程:
https://yaklang.com/docs/intro/
Yakit 视频教程:
https://space.bilibili.com/437503777
Github下载地址:
https://github.com/yaklang/yakit
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
https://yaklang.com/products/download_and_install
Yakit使用文档:
https://yaklang.com/products/intro/
常见问题速查:
https://yaklang.com/products/FAQ

长按识别添加工作人员
开启Yakit进阶之旅


文章来源: https://mp.weixin.qq.com/s?__biz=Mzk0MTM4NzIxMQ==&mid=2247520165&idx=1&sn=5c04e57dd45b71415975004e0f974321&chksm=c2d1f301f5a67a177bf9fef40ec35045790a1234225e854ef8d50f2ce4fc2b97f33c03652c11&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh