使用joern-tools进行代码分析
通过使用joern-tools提供的命令来寻找bugs和vulnerabilities,前半部分提供了使用joern的简短的命令和更长的查询,这些查询说明了joern的工作原理。后半部分提供了能够让人使用joern-tools工具根据特殊需要进行扩展。
导入代码:
./joern
需
要
解
析
的
代
码
目
录
在
n
e
o
4
j
−
s
e
r
v
e
r
.
p
r
o
p
e
r
t
i
e
s
文
件
中
更
改
下
面
的
语
句
o
r
g
.
n
e
o
4
j
.
s
e
r
v
e
r
.
d
a
t
a
b
a
s
e
.
l
o
c
a
t
i
o
n
=
需要解析的代码目录 在neo4j-server.properties文件中更改下面的语句 org.neo4j.server.database.location=
需要解析的代码目录在neo4j−server.properties文件中更改下面的语句org.neo4j.server.database.location=JOERN/.joernIndex/
把路径改成生成的.joernIndex/
打开neo4j控制台可以看到生成的数据已经被导入:
$NEO4J/bin/neo4j console
扩展数据库内容
- 在开始使用joern-tools之前,快速地看一下存在数据库中的代码数据,并且了解一下它是如何获得的。joern-tools通过封装py2neo的库python-joern使用基于web的Neo4J API (REST API)。当使用joern-tools的工具时它通常是不可见的,如果想要知道里面发生了什么,可以把你的浏览器指向:
http://localhost:7474/db/data/node/0
这是图数据库的根节点,也是推荐的节点,从这个结点开始,整个数据库的内容都可以通过使用你的浏览器来得到。你可以浏览所有存在的边的类型和连接边与点的条件。在实际中,你可能并不想使用浏览器来查询数据库。那么joern-lookup就可以用来代替使用。 - 检查节点和边的属性
可以通过使用joern-lookup来自定义查询数据库,joern-lookup默认的查询方式是索引查询。对于Gremlin查询,-g的flag需要被明确。让我们首先使用Gremlin查询检索直接连接到根节点的所有节点:
echo ‘g.v(0).out()’ | joern-lookup -g
如果成功,那么您已经通过joen -tools使用REST API成功地将Gremlin脚本注入到Neo4J数据库中。你可以看到,推荐节点只输出了一个子节点。这个节点有两个属性:“type”和”filepath“。在joern的数据库中,在这个”directory”下,每一个节点都有一个”type”属性。目录节点额外的第二个属性“filepath”,它存储了代表这个节点的完整路径。
如何获得扩展的输出边呢?
echo ‘g.v(0).out().outE()’ | joern-lookup -g | sort | uniq -c
正如证明的那样,目录节点在它的filepath属性中只包含它的路径,它通过IS_PARENT_DIR_OF的类型边来连接到子目录。因此,他在目录层次结构中的位置被编码在图结构中。
Filtering:从一个目录节点开始,我们可以递归枚举它包含的所有文件,并按名称过滤它们。例如,下面的查询返回目录“demux”中的所有文件:
echo ‘g.v(0).out(“IS_PARENT_DIR_OF”).loop(1){true}{true}.filter{ it.file.contains(“/demux/”)’ | joern-lookup -g
文件节点被链接到它们包含的所有定义,即类型、变量和函数定义。在研究函数之前,让我们先快速了解一下节点索引。
快速了解节点索引
节点索引,除了最基本的查询之外,您可能需要在所有查询中使用它。不需要从根节点遍历所有的图数据库,你可以只查看满足他们条件的节点。在底层,这个索引是作为Apache Lucene索引实现的,因此你可以使用完整的Lucene查询语言来检索节点。让我们看一些例子:
echo “type:File AND filepath:demux” | joern-lookup -c
echo ‘queryNodeIndex(“type:File AND filepath:demux”)’ | joern-lookup -g
使用:
echo ‘queryNodeIndex(“type:File AND filepath:demux”).out().filter{it.type == “Function”}.name’ | joern-lookup -g
画出数据库的内容
为了使用户能够快速了解他们数据库的内容,joern-tools提供了使用graphviz来可视化他们的数据库:
- 按名称检索函数
echo ‘getFunctionsByName(“GetAoutBuffer”).id’ | joern-lookup -g | joern-location
使用快捷的getFunctionsByName。python-joern
echo ‘getFunctionsByName(“GetAoutBuffer”).id’ | joern-lookup -g | tail -n 1 | joern-plot-ast > foo.dot - 画出抽象语法树
使用上一句的joern-plot-ast来生成AST的.dot文件
dot -Tsvg foo.dot -o ast.svg; eog ast.svg - 画出控制流程图
echo ‘getFunctionsByName(“GetAoutBuffer”).id’ | joern-lookup -g | tail -n 1 | joern-plot-proggraph -cfg > cfg.dot;
dot -Tsvg cfg.dot -o cfg.svg; eog cfg.svg - 显示数据流边缘
echo ‘getFunctionsByName(“GetAoutBuffer”).id’ | joern-lookup -g | tail -n 1 | joern-plot-proggraph -ddg -cfg > ddgAndCfg.dot;
dot -Tsvg ddgAndCfg.dot -o ddgAndCfg.svg; eog ddgAndCfg.svg - 标记程序切片的节点
echo ‘getFunctionsByName(“GetAoutBuffer”).id’ | joern-lookup -g | tail -n 1 | joern-plot-proggraph -ddg -cfg | joern-plot-slice 1856423 ‘p_buf’ > slice.dot;
dot -Tsvg slice.dot -o slice.svg;
你可能会改掉里面的1856423为其他的数字
通过名字来选择函数
- 通过名字来寻找函数
echo ‘type:Function AND name:main’ | joern-lookup - 使用通配符
echo ‘type:Function AND name:write’ | joern-lookup - 查询设计
echo ‘type:Function AND name:write’ | joern-lookup -c - 输出特定字段
echo ‘type:Function AND name:write’ | joern-lookup -a name - 列出所有函数的简写
joern-list-funcs - 列出所有匹配模式的函数
joern-list-funcs -p 'write
名单签名:echo “getFunctionASTsByName(‘write‘).code” | joern-lookup -g
通过函数内容进行查找
- 通过参数来查找函数
echo “queryNodeIndex(‘type:Parameter AND code:len’).functions().id” | joern-lookup -g
简记: echo “getFunctionsByParameter(‘len’).id” | joern-lookup -g - 从函数的ids到它的位置:joern-location
echo “getFunctionsByParameter(‘len’).id” | joern-lookup -g | joern-location - 把代码输入到text-files:
echo “getFunctionsByParameter(‘len’).id” | joern-lookup -g | joern-location | joern-code > dump.c - 通过位置在编辑器
echo “getFunctionsByParameter(‘len’).id” | joern-lookup -g | joern-location | tail -n 2 | joern-editor
需要位于导入代码或使用完整路径导入代码的目录中 - 按调用查找函数
echo “getCallsTo(‘memcpy’).functions().id” | joern-lookup -g
您还可以在这里使用通配符。当然,可以在函数id上再次使用joen -location、joen -code和joen -editor查看代码。 - 列表调用表达式
echo “getCallsTo(‘memcpy’).code” | joern-lookup -g - 实参列表
echo “getCallsTo(‘memcpy’).ithArguments(‘2’).code” | joern-lookup -g