史上最全 抽丝剥茧代码属性图CPG-第一弹:CPG介绍

阅前声明:文末彩蛋(每期都有哦)~

一、背景

在学习CPG之前,我们要搞清楚以下两个问题:

  • CPG是什么
  • 为什么要使用CPG做代码分析

1.cpg是什么

官网的回答如下:(https://fraunhofer-aisec.github.io/cpg/)

A Code Property Graph (CPG) is a graph-based representation of code which unites several concepts such as an Abstract Syntax Tree (AST), Control Flow Graph (CFG) or Evaluation Order Graph (EOG), Data Flow Graph (DFG) or Control Dependence Graph (CDG), among others, in a single supergraph. This is beneficial because the CPG contains the most relevant information to conduct static program analysis and yet, the graph provides a certain abstraction of the respective programming language.

翻译过来是这样的:

代码属性图(CPG)是一种基于图的代码表示方法,它将诸如抽象语法树(AST)、控制流图(CFG)或评估顺序图(EOG)、数据流图(DFG)或控制依赖图(CDG)等多种概念统一到一个超级图中。这样做的好处是CPG包含了进行静态程序分析最相关的信息,同时,该图还提供了对相应编程语言的一定程度的抽象。

意思就是说:CPG是一种融合多种表示程序结构/某种特征的图的整合,并且CPG还针对不同语言提供了不同的前端解析器,可以自定义解析语言的语法糖。

这么做的好处就是当你基于CPG开发代码分析器时,开发效率会大大提升。从工程角度讲,不再需要分模块地去做语义分析、控制流分析、数据流分析等操作。

同时,其缺点也是显而易见的:

  • 该框架非常的,如果在自己的分析引擎中引入CPG很可能会出现性能问题;
  • CPG中包含的数据量非常大,当我们做简单的程序分析时,就显得有点不必要了;
  • 另外,CPG开源版还在起步阶段(目前231Star),所以稳定性还不是很好

这么说可能不太直观,直接上图,让我们来看看CPG中有什么!

CPG之庞大显而易见~

2. 为什么要使用CPG

1. Supported Languages

支持以下语言:

  • Java
  • C/C++
  • Go
  • Python
  • TypeScript
  • LLVM-IR

并且,其还支持自定义语言前端,这一点还是厉害的!

2. Built-in Analyses

CPG目前支持以下分析:

  • 数据流分析 Dataflow Analysis
  • 可达性分析 Reachability Analysis
  • 常量传播 Constant Propagation
  • 过程内语句执行分析 Intraprocedural Order Evaluation of Statements

3. Accessing the Graph

提供多种使用方式:

  • 图可以导出到图数据库 neo4j
  • CPG可以通过第三方依赖库的方式被引入
  • 提供一个交互式的命令行界面(CLI)来可视化这个图
  • 提供API来查询图中的属性(类似Datalog声明式语言直接从数据库中Query属性)

4. Highly Extensible

CPG拥有高扩展性:

  • 自定义语言前端
  • 自定义Pass(分析过程的一种技术支持,如:TypeHierarchyResolver、SymbolResolver等)
  • 自定义分析方法

5. Handling Incomplete Code

CPG支持分析非编译的项目,若在分析过程中遇到了不存在的类/方法/字段/属性等,其不会崩溃,其有丰富的推断功能,最终会在CPG图上添加一些虚拟节点

二、CPG的执行逻辑

The translation of source code to the graph consists of two main steps. First, the source code is parsed and transferred to the CPG nodes by a so-called Language Frontend. Then, Passes refine the information which is kept in the graph. These two stages are strictly separated one from each other.

大致意思如下:

将源代码转换为图的过程主要包括两个主要步骤:

  • 源代码由语言前端进行解析,并转化为代码属性图(CPG)中的节点
  • 通过Passes对保留在图中的信息进行细化完善。这两个阶段之间严格区分,互不干扰

三、Language及Language Frontend

CPG想要设计一种语言无关的中间表示形式,但是其解析的对象是源代码文件(不是编译后的产物)。因此,其引入了两个概念。

1. Language

第一个概念是Language。它代表编程语言作为一个总体概念,包括以下属性:

  • 语言的名称,例如 C++,Java
  • 用于分隔命名空间的分隔符,如 ::
  • 用于解析它的 LanguageFrontend
  • 额外的 LanguageTrait 实现

每个节点都有一个语言属性,用来指定它的语言

LanguageTrait

不同的语言有不同的语言特性(LanguageTrait),可以实现LanguageTrait接口来扩展。例如以下特性:

  • 是否支持默认参数
  • 该语言是否有结构体或类
  • 是否支持函数指针
  • 该语言是否使用模板或泛型
  • 解析符号、调用、变量时是否需要特殊处理

CPG在执行Pass阶段时会根据指定的语言特性做不同的解析。

2. Language Frontend

语言前端(LanguageFrontend)负责将源代码转换为CPG节点

其依赖某个库(java语言用的是javaparser)来获取AST(抽象语法树),然后设置节点间的AST边,并设置恰当的作用域。

以上操作是一定要做的,其他的操作(如:CallResolver、SymbolResolver等)是可选的,一般由后续的Pass阶段完成。当然,如果想在语言前端处理时添加某些确定的边(如:refersTo边),CPG也是允许的,但一般不建议这么做。

语言前端的生命周期是有限的,仅在翻译阶段存在。在后续执行Pass阶段时,语言前端将不再存在。可以通过LanguageTraits来对不同语言的Pass阶段进行定制化。

四、Pass阶段

1. 什么是Pass

What is a Pass?

Passes get a prebuilt CPG that at least contains the CPG-AST and output a modified graph. Their purpose is to extend the syntactic representation of code with additional nodes and edges to represent the semantics of the program. Passes can be executed in sequence, where the output of the previous pass serves as input of the next pass.

  • 解释:

Passes接收一个预构建的CPG,其中要包含CPG-AST,经过处理后Pass阶段会输出一个经过修改的图。目的是通过添加额外的节点和边来扩展代码的句法表示,以更好地展现程序的语义。这些Pass可以按照序列执行,前一个Pass的输出结果将作为下一个Pass的输入

我们可以继承Pass类并实现其accept方法来实现自定义的Pass。

另外,CPG也支持重写一些方法来修改现有的一些Pass。

2. Pass间的依赖关系

Pass之间可能存在依赖关系一个通道可能依赖于另一个通道添加的信息,这就需要控制Pass的执行顺序。可以通过以下注解来控制Pass的执行顺序:

  • DependsOn(other: KClass<out Pass>, softDependency: Boolean = false) – 被注解的Pass在其他Pass之后执行。如果softDependency设置为false,会自动注册这些Pass。
  • ExecuteBefore(other: KClass<out Pass>, ...) – 被注解的Pass在指定的其他Pass之前执行。
  • ExecuteFirst – 如果可能,被注解的Pass作为第一个Pass执行。
  • ExecuteLast – 如果可能,被注解的Pass作为最后一个Pass执行。
  • RequiredFrontend(frontend: KClass<out LanguageFrontend>) – 只有当使用指定前端时,被注解的Pass才会执行。

公众号推荐

笔者运营自己的公众号,会定时更新代码分析、安全漏洞、热点资讯等信息,感兴趣的读者可以扫码关注一下,感谢支持!!!

提效工具推荐

Everything (https://www.voidtools.com/zh-cn/)

该工具可以快速全局搜索你想要的文件,支持正则表达式,并且只创建一次索引,搜索速度非常快,比windows自带的搜索快n多倍~

其界面如下:

想要了解更多功能的童鞋可以转站官网查询~

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
代码属性(Code Property Graph,CPG)是一种对程序代码进行建模和分析的技术。CPG 将程序代码转换为形结构,其中节点表示程序元素(例如类、方法、变量等),边表示它们之间的关系(例如方法调用、类继承等)。 CPG 在 Java 语言中的应用称为 CPG Java。CPG Java 提供了一种方法,可以将 Java 代码转换为 CPG 结构,从而可以进行更高级别的分析和查询操作。 在 CPG Java 中,程序代码被表示为一个巨大的,其中包含了代码中的各种元素和关系。例如,类和接口被表示为节点,它们之间的继承关系用边表示。方法和函数也被表示为节点,并使用边表示它们之间的调用关系。 使用 CPG Java,我们可以执行各种分析任务。例如,我们可以通过遍历中的节点和边,找到在代码中调用了某个特定方法的所有地方。我们还可以找到使用了特定变量的所有方法,并检查它们之间的依赖关系。 CPG Java 可以帮助开发人员理解和维护代码。通过将代码转换为形结构,我们可以更好地可视化代码之间的复杂关系,并进行更高级别的分析和优化。它还可以用于自动化的代码分析和检查,以帮助开发人员发现潜在的问题和错误。 总而言之,CPG Java 是一种将 Java 代码转换为代码属性的技术,可以用于对程序代码进行建模和分析。它可以帮助开发人员更好地理解和维护代码,并进行各种分析任务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值