用Joern-cli分析代码

官网文档:joern

程序分析常常需要生成一些程序的中间表示,中间表示包括但不限于

  • Abstract Syntax Tree(AST, 抽象语法树)
  • Control Flow Graph(CFG,控制流图)
  • Control Dependence Graph(CPG,数据依赖图)
  • Data Dependence Graph (DDG,数据依赖图)
  • Program Dependence graph (PDG,程序依赖图, = CPG + DDG)
  • Code Property Graphs (CPG,程序属性图, = 前面5种图的总和)

而Joern则是一款很好的生成这些中间表示的工具,可以从github上下载joern-cli命令行工具,Joern支持C/C++和Java编程语言,支持Windows/Mac/Linux平台,不过joern-cli种的bat脚本不太好用,不知道windows下应该怎么用。

Joern-cli命令行交互模式

joern-cli的目录下包括
在这里插入图片描述

joern, joern-parse等均是可执行文件,执行 ./joern 会进入命令行交互模式

在这里插入图片描述
这里以生成下面C语言代码的AST等中间表示为目标

示例代码1

int myfunc(int b) {
    int a = 42;
    if (b > 10) {
        foo(a);
    }
    bar(a);
    return a;
}

由于该示例代码并无控制依赖(按道理说foo(a)应该依赖于b>10,可能有解析错误)和数据依赖,故没有列出。

命令行输入importCode.c.fromString( """ int myfunc(int b) { int a = 42; if (b > 10) { foo(a); } bar(a); } """ )

在这里插入图片描述

生成AST

输入cpg.method("myfunc").plotDotAst
在这里插入图片描述
在这里插入图片描述

生成CFG

输入cpg.method("myfunc").plotDotCfg

在这里插入图片描述

生成CPG

输入cpg.method("myfunc").plotDotCpg14
在这里插入图片描述
可以看到这段代码并没有明确的控制依赖和数据依赖关系,控制流图也是以行(也可以解释为statement)来生成,不过这些中间表示中foo(a);去哪了就不清楚了。

示例代码2

#include<stdio.h>
#include<string.h>

int main() {
  unsigned int first_len = UINT_MAX - 256;
  unsigned int second_len = 256;
  unsigned int buf_len = 256;

  char first[first_len], second[second_len], buf[buf_len];
  int new_len = (first_len+second_len); // <- IDB (negative)

  if(new_len <= 256) {
      memcpy(buf, first, first_len);
      memcpy(buf + first_len, second, second_len); /* <=== */
  }
  return 0;
}

由于示例代码的AST和CPG过于庞大,故没画出。

CFG

在这里插入图片描述这里可以看出CFG中

  • 变量声明语句(如char first[first_len], second[second_len], buf[buf_len];)不会出现在CFG中
  • CFG中一个大的statement会被拆分为几个小的(如unsigned int first_len = UINT_MAX - 256; 可拆分为 变量声明unsigned int first_len,减法UINT_MAX - 256和赋值first_len = UINT_MAX - 256,其中变量声明会被无视,而减法又在赋值之前执行),每个小的statement会作为一个控制流结点出现在CFG中。

CDG

在这里插入图片描述可以看到CDG中,if语句块中的语句会对if条件中的语句有控制依赖。

示例代码3

#include <stdio.h>

int main () {
   int i = 0;
   char c;
   while (i < 10){
   	   getchar(c);
       ++i;
   }
   printf("%d",i);
}

CFG

在这里插入图片描述
可以看出循环语句除了循环体最后一个statement有一个边连回循环条件之外其它跟if语句差不多

CDG

在这里插入图片描述可以看出与if条件的CDG相比,循环语句的CDG多了一条循环条件statement连回自己的边

示例代码4

#include <stdio.h>

int main () {
   int i;
   char c;
   for (i = 0; i < 10; ++i){
   	   getchar(c);
       printf("%c",c);
   }
   printf("%d",i);
}

CFG

在这里插入图片描述

CDG

在这里插入图片描述
可以看到生成CFG和CDG时,

for (i = 0; i < 10; ++i){
    dosomething();
}

i = 0; 
while(i < 10){
    dosomething();
    ++i;
}

的CFG一样。

不过目前如何用joern-cli像joern一样导出代码的图表示的csv文件还不清楚,官网给的是用scala写脚本导出json,不过graph-func.sc脚本好像总是有编译错误,不知道是什么问题。

Joern

joern的目录如下,文档参考

在这里插入图片描述

这是老版本的Joern,现在好像停更了,与Joern-Cli不同的是,这个版本的Joern会对每个输入的.c文件生成一个edges.csv和nodes.csv。

用法如下:./joern-parse output SourceDir

  • SourceDir为存放源代码的文件夹,joern会解析该文件夹下所有.c,.cpp等文件。

  • output存放结果

在这里插入图片描述
针对test1.c生成的edges.csv和nodes.csv

test1.c内容

#include "stdio.h"
#include "string.h"
#include <stdio.h>


void foo()
{
    int x = source();
    if (x < MAX)
    {
        int y = 2 * x;
        sink(y);
    }
}


int main()
{
   foo();
}

这里nodes.csv有几个内容
在这里插入图片描述重要的有key, type, code, location, isCFGnode

  • key为该CPG图结点的索引
  • type表示是什么类型的结点,IdentifierDeclStatement,ArgumentList等等
  • code为该结点对应的代码
  • location包含该结点对应的行号
  • isCFGnode为True表示这是一个CFG结点,为空或False表示AST结点

以上面test1.c的foo函数来说

void foo()
{
    int x = source();
    if (x < MAX)
    {
        int y = 2 * x;
        sink(y);
    }
}

它有4个statement。int x = source();, if (x < MAX), int y = 2 * x;, sink(y);

CPG如下:
在这里插入图片描述那么ENTRY,DECL,PRED,DECL, CALL, EXIT即CFG结点。CFG结点包含的code为一个完整的statement的code。而剩下的即AST结点,AST结点通常只包含一个statement的部分code。

edges.csv包含的域如下:
在这里插入图片描述

  • start表示开始结点的索引,即key
  • end为结束结点的索引
  • type为边类型,这里有12种边
    • IS_AST_PARENT
    • IS_CLASS_OF
    • FLOWS_TO
    • DEF
    • USE
    • REACHES
    • CONTROLS
    • DECLARES
    • DOM
    • POST_DOM
    • IS_FUNCTION_OF_AST
    • IS_FUNCTION_OF_CFG
  • var表示边的值,比如如果两个结点关于变量buf存在数据依赖,那值就是buf

其中

  • FLOWS_TO 表示控制流图(control flow),只连接CFG结点。
  • CONTROLS 表示控制依赖图(control dependency),只连接CFG结点。
  • REACHES 表示数据依赖图(data dependency),只连接CFG结点。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值