代码分析属性图 CPG 介绍

代码解析工具cpg 阅读详情

代码分析工具层出不穷,编译器本身也内置了大量的静态检查,但分析的数据源较为单一。而本文要介绍的,是集众之所长的代码分析属性图 CPG,在漏洞分析上很有帮助。

1、定义

代码属性图(code property graph,简称 CPG) 是一种数据结构,用来通过 DSL(domain-specific language) 查询语句来挖掘代码漏洞。

它的主要思想如下:

  • CPG 将多个程序表示(program representations)整合成一个
  • CPG 数据被存储在图数据库中
  • 通过 DSL 在图数据库中遍历和查询 CPG 数据

2、用处

CPG 整合了 AST(abstract syntax trees)、CFG(control flow graphs)、PDG(program dependence graphs) 到一种数据结构当中。

这种综合的数据表示,使得我们在图遍历当中,可以优雅地组织漏洞扫描的模版。

可以用来分析缓冲区溢出、整型溢出、格式字符串漏洞、内存泄漏等。

2.1、局限性

1、纯静态分析,缺乏对运行时信息的组织(比如数据争用)

2、解决的是通用的潜在漏洞,难以挖掘特定场景下的漏洞

3、暂时缺乏对 IR 层面的分析(待扩展)

3、结构

结合了下面三种不同的表示:

整合成一种表示 - Code Property Graph:

CPG 就是属性图,它包含以下组成部分:

  • 节点及其类型。节点代表程序的组成部分,包含有底层语言的函数、变量、控制结构等,还有更抽象的 HTTP 终端等。每个节点都有一个类型,如类型 METHOD 代表是方法,而 LOCAL 代表是一个局部变量。
  • 有向边及标签。节点之间的边代表它们之间的关系,而标签则是关系的说明。比如一个方法 CONTAINS 包含了一个局部变量。
  • 键值对。节点带有键值对,即属性,键取决于节点的类型。比如一个方法至少会有一个方法名和一个签名,而一个局部变量至少有名字和类型。

4、概念

4.1、CPG (Code Property Graph)

4.1.1、property graph

定义基本的有向图数据结构 G = (V, E, λ, μ),即 graph = (点的集合,有向边的集合,边上标签的计算函数,属性)

Σ 代表字母表,λ : E → Σ

K 代表属性键 key 的集合,而 S 代表属性值 value 的集合,μ : (V ∪ E) × K → S

4.1.2、traversal

遍历函数是 T : P(V) → P(V),P 是 V 的幂集,即 V 中所有子集构成的集合,实际上是把一系列节点映射为另一系列的节点。

还可以获取有向边的输入:

4.2、AST (Abstract Syntax Trees)

抽象语法树 AST,这棵树的编码信息,表达了语句(statements)和表达式(expressions)是如何嵌套组合来生成程序代码的。

AST 是有序的树,它的内部节点代表了运算符操作(如加法或赋值),而叶子节点则关联到操作数(如常量或标识符)。

4.3、CFG (Control Flow Graph)

控制流图 CFG,描述了代码语句(statements)执行的顺序,以及某一执行路径上的某处的状态。在图中,语句(statements)和判断(predicates)用节点来表示,而这些节点用有向边来连接,表示控制的转换。每条边需要标上 true、false、空 的标签。

CFG 可以用 AST 来生成:首先,结构化的控制语句(如 if、while、for)先用来构建初始的 CFG;然后,添加上非结构化的控制语句(如 goto、break、continue),来逐步修正这个初始的 CFG。

4.4、PDG (Program Dependence Graphs)

PDG 用来找出会影响某条语句上的变量值的所有语句和判断。PDG 展现了语句和判断之间的依赖关系。一般该图以两种类型的边来构造:数据依赖边(data dependency edges)表示会影响某语句的变量;控制依赖边(control dependency edges)表示判断语句对于变量值的影响。

PDG 的边可以从 CFG 计算得来,通过先判断已定义的变量的集合、每条语句使用到的变量的集合,然后计算每条语句和判断的定义在哪。

5、转换工具 llvm2cpg

llvm2cpg - 将 LLVM bitcode 格式转换成 CPG 图

$ clang -S -emit-llvm -g -O1 main.c -o main.ll 
$ llvm2cpg -output=/tmp/cpg.bin.zip main.ll

下面的 bitcode (IR)内容:

define i32 @sum(i32 %a, i32 %a) {   
    %r = add nsw i32 %a, %b   
    ret i32 %r 
}

可以转换成更高级抽象的形式:

i32 sum(i32 a, i32 b) {   
    i32 r = add(a, b);   
    return r; 
}

5.1、实现细节

当要用 LLVM 来支持 CPG,首先的问题就是:我们要怎么把 bitcode 映射为 CPG?

5.1.1、指令语义

我们可以把一些 LLVM 的指令转换成 CPG 的运算符。比如:

  • add, fadd -> <operator>.addition
  • bitcast -> <operator>.cast
  • fcmp eq, icmp eq -> <operator>.equals
  • urem, srem, frem -> <operator>.modulo
  • getelementptr -> 组合 <operator>.pointerShift, <operator>.indexAccess, 和 <operator>.memberAccess 依赖于 GEP 操作数的类型

但有一种指令我们无法映射为 CPG 的,那就 phi 指令,在 CPG 中没有 phi 节点的概念,所以我们需要用 reg2mem 的运算方法把 phi 指令去掉。

5.1.2、冗余

Clang 默认会生成大量的冗余指令。

define i32 @sum(i32 %0, i32 %1) {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
  store i32 %1, i32* %4, align 4
  %5 = load i32, i32* %3, align 4
  %6 = load i32, i32* %4, align 4
  %7 = add nsw i32 %5, %6
  ret i32 %7
}

而不是更加精简的版本:

define i32 @sum(i32 %0, i32 %1) {
  %3 = add nsw i32 %1, %0
  ret i32 %3
}

一般情况下,这不是什么问题,但它增加了数据流追踪的复杂度,而且很没必要地增加了图的大小。一个可以解决的方法是,先对 bitcode 跑一下优化。但最终 LLVM 还是把这种选择权交给用户来决定。

5.1.3、类型等价判断

在我写的一篇译文里有相关更具体的介绍和解决方案《【译】LLVM 类型相等判断》,或者可以直接看原文。下面简单地介绍下问题:

如果有相同结构相同名字的两个模块,被加载到同一上下文,LLVM 会重命名其中一个来避免命名冲突。

; Module1
%struct.Point = type { i32, i32 }

和

; Module 2
%struct.Point = type { i32, i32 }

当加载到同一个上下文时:

%struct.Point = type { i32, i32 }
%struct.Point.1 = type { i32, i32 }

我们需要对这些类型进行去重,以保证最终生成的图中,只会有一个 Point 的节点。这就需要我们判断两个类型是否是等价的。

5.2、总结

用 LLVM bitcode 的方式有以下的优点和局限性:

  • LLVM 语言的接口比 C 和 C++ 更轻量
  • 很多抽象层的细节,在 IR 层不会有体现
  • 程序需要被编译,因此会限制了程序的语言扩展范围

6、相关产品

现在,CPG 已经被以下几个工具支持了:

  • Ocular- 支持 Java, Scala, C#, Go, Python, 和 JavaScript 语言
  • Joern- Ocular 的开源部分,支持 C 和 C++
  • Plume- 开源工具,支持 Java Bytecode

6.1、Joern

Joern 有以下几个重要特性:

  • Fuzzy Parsing of C/C++. 模糊解析,用于在编译环境和部分文件的缺失的情况下,进行解析。
  • Code Property Graphs. 模糊解析的结果会被存储到 CPG 格式的数据库当中。
  • Search Queries. 提供了基于 Gremlin-Scala 扩展的查询语言。
  • Extendable via CPG passes. 支持自定义扩展来添加或消费数据信息。

Joern 可以为 C/C++ 代码创建以下几种中间表示:

  • Abstract Syntax Trees (AST)
  • Control Flow Graphs (CFG)
  • Control Dependence Graphs (CDG)
  • Data Dependence Graphs (DDG)
  • Program Dependence graphs (PDG)
  • Code Property Graphs (CPG14)

6.1.1、Joern 使用例子

有了 Joern 和 llvm2cpg,就可以愉快地玩耍了:

  1. 转换程序为 LLVM Bitcode
  2. 生成 CPG
  3. 加载 CPG 到 Joern 当中,然后进行分析
$ cat main.c
extern int MAX;
extern int source();
extern void sink(int);
void foo() {
  int x = source();
  if (x < MAX) {
    int y = 2 * x;
    sink(y);
  }
}
$ clang -S -emit-llvm -g -O1 main.c -o main.ll
$ llvm2cpg -output=/tmp/cpg.bin.zip main.ll

现在我们已经把 CPG 保存到 /tmp/cpg.bin.zip ,之后就能加载到 Joern,然后尝试分析是否有从 source 函数到 sink 函数的流:

$ joern
joern> importCpg("/tmp/cpg.bin.zip")
joern> run.ossdataflow
joern> def source = cpg.call("source")
joern> def sink = cpg.call("sink").argument
joern> sink.reachableByFlows(source).p
List[String] = List(
  """_____________________________________________________
| tracked               | lineNumber| method| file   |
|====================================================|
| source                | 5         | foo   | main.c |
| <operator>.assignment | 5         | foo   | main.c |
| <operator>.lessThan   | 6         | foo   | main.c |
| <operator>.shiftLeft  | 7         | foo   | main.c |
| <operator>.shiftLeft  | 7         | foo   | main.c |
| <operator>.assignment | 7         | foo   | main.c |
| sink                  | 8         | foo   | main.c |
"""
)

参考

CPG_14S&P Modeling and Discovering Vulnerabilities with Code Property Graphs Modeling and Discovering Vulnerabilities with Code Property Graphs S&P 14 提出代码属性图的建模方式,将抽象语法树、控制流图、程序依赖图结合在一起。 定义属性图(property graph):[V,E,λ,μ] 是由顶点(vertex/node)、边(edge)、标签(label)、属性(property) V是图中的顶点集合, E是图中有向边的集合, E ⊆ (V × V ) λ是给图中每条边分配标签的标记函数,λ : E 阅读详情

相关推荐

Joern实战:5分钟将C/Java源码变成可交互的漏洞依赖图(PDG/CPG)

本文详细介绍了如何使用Joern工具快速将C/Java源代码转换为可交互的漏洞依赖图(PDG/CPG)。通过极简环境配置、源码解析、交互式分析和可视化输出,帮助开发者高效定位代码中的安全风险。Joern的开源特性使其成为代码安全分析的强大工具,特别适用于快速生成控制流图和程序依赖图。

dengxiangbao3167的博客 476

代码属性图(CPG)

代码属性图是一种用于描述程序代码结构和属性的图形表示方式。它将程序代码中的各种元素(如类、函数、变量等)以节点的形式表示,节点之间的连接则表示它们之间的关系。简单来说就是由AST,CFG,PDG整合而成的一种数据架构。

爱远方的博客 2350

​Joern代码分析工具解析

Joern 是一款专注于代码安全分析的开源静态分析工具,旨在帮助开发者、安全研究人员自动化识别代码中的漏洞与潜在风险。其核心设计理念是通过构建代码属性图(Code Property Graph, CPG)​,将代码的语法、语义、数据流、控制流等多维度信息统一建模,从而支持复杂的代码逻辑推理。

编程小栈 2171

史上最全! 代码属性图CPG:CPG中的DFG(Data Flow Graph)

史上最全 代码属性图CPG讲解:DFG数据流图(Data Flow Graph)

qq_44826960的博客 1591

Joern实战:用代码属性图(CPG)给你的C项目做一次‘安全体检’

本文详细介绍了如何使用Joern工具通过代码属性图(CPG)对C语言项目进行安全分析。从环境配置到实战演练,展示了如何检测缓冲区溢出、格式化字符串等常见漏洞,并利用数据流追踪和可视化技术提升代码审计效率。特别适合中高级开发者和安全研究人员提升静态代码分析能力。

weixin_29205061的博客 191

Joern实战:从零构建代码属性图挖掘漏洞

本文详细介绍了如何使用Joern从零构建代码属性图(CPG)进行漏洞挖掘。通过环境搭建、基础查询、数据流分析等实战步骤,帮助开发者掌握Joern的核心功能,提升代码安全分析能力。文章还分享了高级技巧和性能优化方法,适用于C/C++、Java等多种编程语言的漏洞检测。

weixin_29209825的博客 430

CPG与AST、CDG、CFG、DDG、PDG

​​CPG 是超级图​​:将 AST、CFG、CDG、DDG、PDG 统一整合,形成多属性、多关系的网络。​​典型工具​​:Joern、CodeQL 等静态分析工具的核心模型。​​适用场景​​:漏洞检测(如 SQL 注入、缓冲区溢出)、代码优化、逆向工程。通过 CPG,开发者可以避免在多图之间切换,直接在一个模型中完成复杂分析。

专注最新最热的AI知识学习,以实战方式总结心得。 1471

从命令行到交互终端:Joern实战绘制代码属性图全流程解析

本文详细解析了如何使用Joern工具从命令行到交互终端绘制代码属性图的全流程。涵盖AST、CFG、CDG、DDG等核心图的生成方法,提供实战案例和性能优化技巧,助力开发者高效进行代码审计和漏洞挖掘。

weixin_29587015的博客 141

Joern快速开始:5个步骤构建你的第一个代码分析项目

Joern是一个基于代码属性图(CPG)的开源代码分析平台,支持C/C++、Java、二进制文件、JavaScript、Python、Kotlin等多种编程语言。这个强大的代码分析工具能够帮助开发者和安全研究人员快速发现代码中的安全漏洞和潜在问题。本文将为你提供一个完整的Joern快速入门指南,通过5个简单步骤让你快速上手这个专业的代码分析平台。 ## 🚀 第1步:环境准备与安装 在开始使用

gitblog_01188的博客 424

Tabby:基于代码属性图与污点分析的Java静态代码审计实战

在软件安全领域,静态应用程序安全测试(SAST)是识别代码中潜在安全漏洞的关键技术。其核心原理是通过分析源代码或字节码,在不运行程序的情况下,追踪数据流和控制流,以发现从不可信输入源到敏感操作汇点的危险路径。这项技术的核心价值在于能在开发早期发现漏洞,降低修复成本,并适用于对代码进行深度、定制化的安全审查。典型的应用场景包括对金融、互联网企业核心业务系统的代码审计,以及第三方组件供应链安全分析。本文聚焦的Tabby工具,正是SAST技术的一种创新实践,它通过构建代码属性图(CPG)并利用Neo4j图数据库进

weixin_28607671的博客 347

llvm2cpg:LLVM符合代码属性图

llvm2cpg llvm2cpg是将LLVM位代码转换为代码属性图(CPG)的工具。 可以通过或进一步分析CPG。 首先,请务必。 之后,继续并学习如何。 如果您有任何疑问,请随时或进行。

Joern(版本v1.0.141) 的简易教程

这篇文章主要介绍一下Joern v1.0.141的使用,官方文档见这:https://joern.io/docs/。 之前的博客主要集中在讲joern 0.3.1的用法,官方文档:https://joern.readthedocs.io/en/latest/ 由于joern 0.3.1的安装比较繁琐,我没成功安上,倒是新版本很容易地安好了。(可能过个几年,这个新版本也变成了老版本=_=) 言归正传,Joern的使用流程比较简单,主要分为两个部分。 导入代码生成代码属性图CPG 首先我们可以从github上找

^_^ 3110

joern:基于代码属性图的CC++JavaBinary开源代码分析平台

约恩 Joern 的文档可在此处获得: : 快速安装 wget https://github.com/ShiftLeftSecurity/joern/releases/latest/download/joern-install.sh chmod +x ./joern-install.sh sudo ./joern-install.sh joern Compiling (synthetic)/ammonite/predef/interpBridge.sc Compiling (synthetic)/ammonite/predef/replBridge.sc Compiling (synthetic)/ammonite/predef/DefaultPredef.sc Compiling /home/tmp/shiftleft/joern/(console) ██╗ █████

使用joern导出并可视化代码图结构

Joern 是一个用于对源代码、字节码和二进制代码进行强大分析的平台,支持C/C++,Java等多种编程语言。它生成代码属性图(CPG),即用于跨语言代码分析的代码图形表示。代码属性图存储在自定义的图数据库中。这使得可以通过使用基于 Scala 的领域特定查询语言编写的搜索查询对代码进行挖掘。Joern 的开发目标是为静态程序分析中的漏洞发现和研究提供一个有用的工具。outdir 文件夹下会生成多个dot文件,我们取其中一个(如0-cpg.dot)进行。关于Joern的更多详细查询语句见。

阿航的博客 990

OpenClaw本地部署教程

本文详细介绍了在Windows 11系统上部署OpenClaw与Ollama本地模型的完整流程。主要内容包括:硬件要求说明、Node.js环境配置、Ollama模型安装与定制(重点扩展上下文窗口至32768 tokens)、OpenClaw核心框架安装与对接、常见问题解决(如模型上下文窗口过小报错)以及可选技能扩展和飞书接入方案。部署全程约需1-2小时,强调使用备用设备或虚拟机以确保安全,并提供关键配置参数和排错命令。该方案实现了"数据不出门、推理本地化"的私有化部署目标。

技术引领业务创新 2575

Docker部署OnlyOffice踩坑实录:解决editor.bin下载失败的3种姿势

本文详细解析了Docker部署OnlyOffice时editor.bin下载失败的常见原因,并提供了三种核心解决方案。重点剖析了容器网络配置、Nginx反向代理(特别是proxy_pass设置)以及安全策略调整,帮助开发者彻底解决静态资源加载问题,确保文档协作平台稳定运行。

weixin_29281941的博客 870

ShiftLeft 学习笔记(三)

在How to Query a CPG 章节中,提到了简单地对代码属性图进行查询的操作,本节对查询操作进行深入的学习。 How to Query a CPG 一旦Ocular为您的应用程序创建了一个代码属性图(CPG),您就可以使用查询来仔细检查CPG(以及您的应用程序)。 有两种类型的查询:默认和自定义。 注意:在研究数据流时,我们建议使用策略来代替查询。本文的最后将包含关于查询和策略之...

water_likly的博客 1622

Synology-群晖(三)DSM7.0系统Video Station无法播放DTS eac3解决方案

群晖升级DSM7.0后,发现部分DTS eac3解码的视频无法通过Vedio Station 3.0.1-2067进行播放,提示不支持该格式视频,初步判断是无法加载ffmpeg解码导致,网上搜了很多处理办法都没有办法解决,最终在知乎上看到一片文章,按此办法解决了这个问题,目前经过验证,该方案完美支持最新版本Video Station 3.0.1-2067,验证系统为DSM7.0和DSM7.0.1,这里使用的NAS为 Vmware虚拟机 黑群晖 演示。大概步骤如下: 添加这个社群来源 http://p

weixin_45827203的博客 3万+

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

代码属性图CPG的介绍,其包含丰富的代码信息,且含有推断模块,扩展性强,是一款很强大的静态代码分析框架。

qq_44826960的博客 2228

SRAM故障排查实战:如何用Nano Prober定位6T存储单元的异常点

本文详细介绍了在SRAM故障排查中,如何运用Nano Prober(纳米探针)技术精准定位6T存储单元的内部异常。面对传统方法难以发现的电性参数漂移(如晶体管阈值电压偏移)或微小物理缺陷,Nano Prober能直接对单个6T单元内的晶体管进行I-V特性测量,结合失效模式分析,有效解决读写错误等疑难问题,是芯片失效分析的关键工具。

v5w6x的博客 664

Fluent新手避坑:遇到‘Floating point exception’别慌,这7个排查步骤帮你搞定

本文为Fluent新手提供了7个排查'Floating point exception'错误的实用步骤,包括边界条件检查、时间步长优化、求解器配置等关键技巧。通过系统化的诊断流程,帮助用户快速定位并解决CFD仿真中的浮点异常问题,提升计算稳定性。

weixin_42531886的博客 285

史上最全! 抽丝剥茧代码属性图CPG

史上最全 抽丝剥茧代码属性图CPG系列

qq_44826960的博客 1459

保姆级教程:手把手调试PX4Ctrl的油门映射与姿态控制(附ROS节点配置)

本文提供PX4Ctrl的深度调参指南,涵盖油门映射、姿态控制及ROS节点配置等关键环节。通过详细解析PX4控制器的核心逻辑、递归最小二乘法(RLS)参数估计及状态机设计,帮助开发者优化无人机飞控性能。附实战案例与安全调试建议,适合PX4开发者进阶学习。

weixin_30363981的博客 382

史上最全 抽丝剥茧代码属性图CPG-第二弹:CPG中的DFG-1

此处与我之前写的文章“SAST-数据流分析方法-理论”(加链接)讲的ICFG的构建方法类似,笔者认为这种基础性质的东西还是有必要掌握的,建议对ICFG构建不熟悉的同学点链接再学习一下~OK,目前为止,CallExpression的DFG构建过程已经验证完成,后续的其他类型的节点的验证过程直接贴图了,不再赘述,大家直接看图就OK~可以看到,结果与源码是对应的,好,我们接着往下走,看看真实的DFG边是不是像上文说的那样构建的~,这里给大家讲一下,cpg的CallExpression有两个子类,一个是。

qq_44826960的博客 1239

YOLOv8【第七章:损失函数篇·第1节】一文搞定,IoU系列损失函数!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 1195

第一节:Vben Admin介绍和初次运行

本文是【实战Vben Admin + Python】的第一节,本文内容主要是介绍Vben Admin框架和我们后端使用的技术,开发环境和工具的准备本节文章的目的是Vben Admin的简单介绍,通过配置可以让项目前端运行起来,由于项目默认开启了mock,展示的都是静态模拟数据,我们在此基础上,下一节将研究分析下Vben Admin的目录。为我们后端搭建准备。

cuiwin的专栏 7409
上一篇: 【译】LLVM 类型相等判断
下一篇: 《WebAssembly 原理与核心技术》笔记
流左沙
博客等级 码龄11年 46粉丝 55原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值