目前源码分析领域存在很多优秀的静态分析工具,比如 Fortify、Joern、codeql 等,在二进制分析领域这类工具则很少见,本议题将介绍演讲者在二进制程序分析工具上的探索。
一起来回顾下罗思礼在SDC2024 上发表的议题演讲:《探秘语法树:反编译引擎驱动自动化漏洞挖掘》
罗思礼:安全研究员
*以下为速记全文
大家好,我是罗思礼,今天给大家带来我最近在二进制分析领域的一些探索,这是前段时间在解决一些逆向困难时想到的思路。
当时我遇到的第一个困难是目标软件有很多的二进制模块,它分散在不同的进程和共享库中,逆向时需要逐个打开 IDA 实例分析比较麻烦,而且IDA插件、脚本无法实现跨模块分析。
面临的第二个难点是同类问题排查,目前针对二进制目标缺乏自动化分析工具,可以去批量的去排查类似问题。但这种情况的话在源码领域却是不一样的,它有很多类似的工具可以用,比如 codeql、Joern、Fortify 等。
我当时的第一个思路是利用图数据库和 IDA 的 CFG 生成跨模块的调用路径分析、字符串引用分析等。
思路是利用 IDA脚本将 CFG 和字符串引用导到一个图数据库,然后我们给它建好对应的边,之后就可以去利用图数据库引擎,快速查询各种路径、引用关系,之后再用对这些路径做一些过滤、清洗,可以辅助我们去分析。
进一步探索后发现可以考虑将 IDA 等反编译工具的分析结果与源码分析工具结合,就能复用源码分析领域的能力了。
对目前业界反编译工具进行分析后,考虑到反编译效果、开发难度决定基于 IDA 开发。
IDA 反编译流程如下:
它首先将汇编指令转换为它的中间语言(microcode),然后然后再在microcode上面做一些反编译的算法,然后最终会生成ctree,即IDA的语法树。
ctree 由 cexpr_t 和 cinsn_t 组成,可以通过 op判断 citem_t 的具体类型,然后根据类型的定义获取每个语法树节点的操作数。
以二元运算符为例,通过 op 的值确定二元运算符的类型, x是左成员,y是右成员,右图是一个实例,它的x是 result,然后y的话是一个number,它是一个立即数。
完成对 IDA 语法树的分析后,就可以开始开发插件将语法树的信息导出,便于后续分析,考虑到开发便捷、IDA版本兼容等特点,决定使用 IDA Python 开发。
导出后的语法树结构如下(具体的代码细节可自行下载查看):
拿到语法树信息后,就需要考虑如何将其与源码分析工具结合,下面介绍一下源码分析工具相关细节。
两个工具的区别在于主要的核心区别就在于 codeql 基于编译的,它提取的信息也更精准,但是问题是在于 codeql 本身是不允许商用的,所以只能个人在工作之外使用。
Joern 的特点是不需要编译,这个条件对于一下审计项目来说是非常友好的。
下面先来介绍 Joern 的技术原理:
它使用不同的工具分析源码,提权源码的语法树,然后基于语法树构建 CFG、DDG 等,生成 CPG,之后用户可以编写规则对 CPG 进行分析。
目前 Joern 也支持使用 Ghidra 分析二进制,但是他没有利用反编译的信息,而是在 pcode 指令上展开分析,这样的话对于规则的编写是比较麻烦的,同一种漏洞模式在指令层面可能会有多种表示。
其次很多情况下我们使用扫描工具时首先会人工分析目标,然后对 IDB 处理,这样反编译后代码会变得更加结构化,利于分析但是在指令层面这些信息是没有的。
以及反编译过程本身会对代码进行优化,删除冗余的代码,这样我们在进行规则扫描时也能提升性能。
Joern 支持的语言和相关代码分布如下:
其中 x2cpg 是基础库,提供构建CPG 的基础 API,其他模块就是根据不同语言的语法树结构调用 x2cpg 生成 CPG。
Joern 在实现层面的特点是将所有的指令转换为函数调用,比如 + 运算符就会通过 .addition函数调用表示。
下图是构建 + 运算符的代码片段:
完成对 Joern 实现原理的分析后,就要考虑如何进行开发,我们目前有Json表示的语法树,php2cpg 模块正好也是以 Json 为输入,于是基于 php2cpg 实现开发,降低工作量。
部分的代码实现如下:
大致思路就是根据导出的语法树结构构建 CPG 需要的 AST 和 CFG,开发过程可以通过绘制 AST、CFG、DDG等代码图判断图是否构建正确。
CodeQL 通过 Extractor模块提取源码信息到 trap 文件,最后将其转换为代码数据库。
目前核心 Extractor (C/Java)闭源,其他的提取器是开源的,通过分析这些开源的提取器可以了解 CodeQL 的一些技术细节,其工作流程如下:
如果要让 CodeQL 支持一个新语言或者新格式最重要的就是生成对应的 trap 文件, trap 的文件格式如下:
Trap 文件生成后,CodeQL 需要配合对于的 dbscheme 文件才能了解每个 trap 对象的含义,同时配合需要对应语言的 qll 库才能进行代码查询。
还是以二元表达式为例,其在 trap 文件中的表示如下:
其他类型的语法元素也是类似的表示,详细可见议题材料,在分析 CodeQL 表示程序的语法和格式后就可以进行具体的代码开发,为了降低工作量,决定基于一个现有的提取器开发 IDA 反编译信息分析工具,最终是基于 go 语言的提取器完成开发。
go-extractor核心就是维护几张表,即表达式表、语句表以及类型表,最后根据解析的结果生成对应表中的元素。
生成 trap 文件再结合 go 语言的 dbscheme 就能生成数据库,通过 vscode 插件进行查询也能跳转到对应的语法树节点。
图中是一个跨二进制数据流的场景,使用编译好的 ida2codeql 分析二进制并生成数据库。
ida2codeql.bat 二进制文件目录保存数据库的目录。
然后编写查询即可获取对应的路径:
下面是一个使用 Joern 分析 MIPS 架构命令注入漏洞的案例:
使用joern-ida 分析二进制并生成 CPG 后就可以通过 Joern 的查询语法进行查询。
最后总结一下本次演讲:
相关工具开源地址:
1.https://github.com/hac425xxx/joern-ida
2.https://github.com/hac425xxx/ida2codeql
峰会议题PPT及回放视频已上传至【看雪课程】:https://www.kanxue.com/book-leaflet-195.htm
【已购票的参会人员可免费获取】:我方已通过短信将“兑换码”发至手机,按提示兑换即可~