快速入門joern

官網給了一個簡單的教程,這篇文章就是按github上的文檔來實踐的。

網址:https://github.com/ShiftLeftSecurity/joern/blob/master/docs2/docs/quickstart.mdx
這個工具的作者最近更新頻率好高。太強了。

獲取樣本程序

這裏用joern作者提供的一個樣本程序叫x42

$ git clone [email protected]:ShiftLeftSecurity/x42.git

如果遇到下面這個問題:permission denied (publickey)

在這裏插入圖片描述
可以使用這個鏈接的方法來解決:https://baijiahao.baidu.com/s?id=1628034638876029219&wfr=spider&for=pc

打開joern的shell

在joern的文件夾下,運行./joern即可打開shell。這個joern shell是基於scala的REPL,REPL類似於python的IDLE。作者提到,如果沒用過scala也沒關係,仍然可以用joern的命令做到狠多事情。如果很熟悉scala的話,你會感嘆它的靈活性。

導入代碼

這裏就不像上次那篇博客用joern-parse來導入代碼,shell裏也可以直接使用importCode命令導入代碼。

importCode(inputPath="./x42/c", projectName="x42-c")
  • inputPath是代碼路徑
  • projectName是工程名稱,下次用joern就可以直接使用open("x42-c")打開

在這裏插入圖片描述

查詢代碼屬性圖

馬上就要用joern和代碼屬性圖來分析程序了。joern的程序分析的實現是基於查詢語言的,一種專門爲代碼屬性圖設計的語言。它包含了代碼屬性圖各種各樣節點的有用表示,以及有用的函數來查詢它們的屬性及它們之間的關係。代碼屬性圖中最頂層的入口點加載在內存中。然後查詢語言中的根對象叫cpg,如果我們在shell裏輸入cpg,只會返回一個id,並沒有什麼卵用。

在這裏插入圖片描述

我們首先學習一個有用的技巧,輸入cpg.然後按TAB鍵,會列出cpg可用的方法。

在這裏插入圖片描述
查看關於cpg的描述信息可以輸入help.cpg查看描述

res12: String = """
Upon importing code, a project is created that holds an intermediate
representation called `Code Property Graph`. This graph is a composition of
low-level program representations such as abstract syntax trees and control flow
graphs, but it can be arbitrarily extended to hold any information relevant in
your audit, information about HTTP entry points, IO routines, information flows,
or locations of vulnerable code. Think of Ocular and Joern as a CPG editors.

In practice, `cpg` is the root object of the query language, that is, all query
language constructs can be invoked starting from `cpg`. For example,
`cpg.method.l` lists all methods, while `cpg.finding.l` lists all findings of
potentially vulnerable code."""

輸入cpg.help可以查看cpg下面各個方法的描述

res13: String = """Available starter steps:
____________________________________________________________________________
 step             | description                                            |
===========================================================================|
 .all             | All nodes of the graph                                 |
 .argument        | All arguments (actual parameters)                      |
 .arithmetic      | All arithmetic operations                              |
 .assignment      | All assignments                                        |
 .call            | All call sites                                         |
 .comment         | All comments in source-based CPGs                      |
 .controlStructure| All control structures (source-based frontends)        |
 .file            | All source files                                       |
 .identifier      | All identifier usages                                  |
 .jumpTarget      | All jump targets, i.e., labels                         |
 .literal         | All literals, e.g., numbers or strings                 |
 .local           | All local variables                                    |
 .member          | All members of complex types (e.g., classes/structures)|
 .metaData        | Meta data blocks for graph                             |
 .method          | All methods                                            |
 .methodRef       | All method references                                  |
 .methodReturn    | All formal return parameters                           |
 .namespace       | All namespaces                                         |
 .parameter       | All parameters                                         |
 .returns         | All actual return parameters                           |
 .tag             | All tags                                               |
 .typeDecl        | All declarations of types                              |
 .types           | All used types                                         |

"""

首先來看一下x42程序:

// X42.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
  if (argc > 1 && strcmp(argv[1], "42") == 0) {
    fprintf(stderr, "It depends!\n");
    exit(42);
  }
  printf("What is the meaning of life?\n");
  exit(0);
}

這個程序主要分爲兩個部分:

  1. 程序向STDERR寫了什麼東西嗎?
  2. 如果有個調用寫了STDERR,那這個傳入x42程序的參數的值是否是有條件限制的呢?

Joern使我們很容易回答這兩個問題。回答第一個問題,我們只需要搜索圖裏屬性爲CALL的節點,然後使用filter直接選擇那些和類型爲ARGUMENT且值爲stderr的節點有關係的CALL節點。

cpg.call.filter(_.argument.code("stderr")).l 

結果如下:

在這裏插入圖片描述

這個查詢告訴我們確實有個地方向STDERR寫了點啥玩意。接下來,我們看第二個問題。由於我們分析的程序是用C語言寫的,所以我們在代碼屬性圖裏搜索main函數裏的argcargv參數,這些參數可能會觸發寫STDERR的調用。基於上一步的查詢,現在我們可以使用astParent來移到代碼屬性圖的抽象語法樹層面來,而找到更多的關於fprintf調用的信息。移到AST層,只給了我們一個block,並不是很有用:

cpg.call.filter(_.argument.code("stderr")).astParent.l

在這裏插入圖片描述

另外一層給了我們一個if語句,更有用:

cpg.call.filter(_.argument.code("stderr")).astParent.astParent.l

在這裏插入圖片描述

這個ControlStructure裏的code屬性告訴我們,寫STDERR的調用是基於argcargv的。

關閉工程

現在我們完成了分析,讓我們關閉工程。不需要擔心會丟失數據,因爲x42-c工程在importCode的時候就創建完畢了。

close

在這裏插入圖片描述
最後,離開joern,按ctrl-D或者輸入exit.

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章