源码二进制比对工具Pigaios
Pigaios原理简介#
目的: 为了解决符号表问题
两种方案:
- 编译源码,使用 Diaphora (or BinDiff) 导出符号表,导入符号表缺失样本
- 从源码题符号表,导入符号表缺失样本
第二种方法好处在于不需要完全编译,因为对于旧的源码,有的很难编译成功
工作流程#
- 解析源代码,并从每个函数的抽象语法树(AST)中提取信息。
- IDA导入从源代码提取的包含源码信息的数据库。
- 查找在C源代码和IDA数据库中找到的函数匹配。
- 找到没有误报的初始匹配项后,从调用图中找到更多匹配项。
- 使用“专家系统”和“基于机器学习”的系统进行评分。
- 同样,将给定代码库的所有结构和枚举导入IDA数据库(这在IDA中并不简单)。
解析函数#
二进制:通过IDA
源码:通过CLang,提取
- 字符串常量
- 循环次数、条件判断、函数调用、全局变量
- switch信息
- 函数调用信息
- 是否为递归函数
特征匹配#
常规方法#
完全匹配#
首先是百分百匹配:为了达到零误报的目的

作者实验结果为在4817个函数中找到了90完全匹配,虽然数目少,但胜在百分百确认,没有误报,不会对分析造成误导。
启发式方法#
为了找到更多的匹配,就需要一些启发式信息了
启发式:
- 调用图
- 临近函数
- 特殊的callee
- 少见的常量特征
机器学习方法#
多分类,使用以下算法
综合考量#
当常规算法和ML结果都表现很好时,就说明匹配度very very good,两者可相互印证
Pigaios使用指北#
Pigaios是一款源码二进制比对工具,在实际二进制样本分析中,带符号表的样本极其少见,这个时候工具的作用就显现出来了。
安装#
在提取源码特征的机器(例如ubuntu)上安装依赖如下:
1 | $ apt-get install clang python-clang-5.0 libclang-5.0-dev python-colorama python-sklearn |
在装有IDA的机子上也同时安装以下:
1 | $ pip install clang-5 colorama scikit-learn |
源码特征提取过程#
下以https://zlib.net/zlib-1.2.11.tar.gz
为例
生成项目信息文件#
在源码根目录下
1 | $ python /path/to/pigaios/srcbindiff.py -create |
默认生成文件sbd.project
,内容为CXX,LLVM等配置信息,以及源码信息
1 | #################################################### |
由于实际上example
、test
等目录包含的是测试样例,可以选择去除对这些文件的分析
提取源码特征#
1 | $ python /path/to/pigaios/srcbindiff.py -export |
结果存储在.sqlite
文件中,在处理过程中会有库文件缺失,以及一些其他的error和fetal,但是没关系,Pigaios都会处理
可以简要查看一下存了哪些信息,如下:
包括调用图信息,常量信息,函数信息,源文件信息
调用图信息
常量信息
都是字符串常量
函数信息
巨长,这里以tsv格式给出第94行和第127行两条记录,具体字段如下,提取了条件信息,switchcase信息,调用信息等

1 | 94 44176 inflate __int64 __fastcall() 289 21 ["invalid block type", "incorrect data check", "too many length or distance symbols", "invalid stored block lengths", "invalid literal/length code", "unknown compression method", "incorrect header check", "header crc mismatch", "invalid distances set", "invalid code lengths set", 595056260442243601, "(I", "unknown header flags set", "invalid window size", "invalid distance too far back", "invalid distance code", "incorrect length check", "invalid literal/lengths set", "invalid bit length repeat", "invalid code -- missing end-of-block", "`\u0007"] 1 1 [[31, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]]] 6 22 {".crc32": 12, ".adler32": 4, "inflate_table": 3, ".memcpy": 5, ".__stack_chk_fail": 1, "inflate_fast": 1} 1 1 0 ["incorrect", "header"] |
源文件信息
不知道为啥是空的
源码二进制比对#
打开编译好并stripped掉的libz.so.1.2.11
,运行pigiaos脚本sourceimp_ids.py
可能因为IDA版本原因,需要在Indent command
中去掉-kr
选项,匹配结果如下
Diff pseudo-code
是将二进制函数反编译并和源码比较,由于颜色原因看不清,可能是因为我的IDA用了黑色主题。
左侧为二进制函数F5结果,右侧为源码函数。
show match reason
显示匹配原因

import all functions
不是很好用,有错误导入不进来,应该是IDA版本原因

注意#
值得一提的是,从效果来看,strip对匹配结果影响很大,当未stripped时,可以获得31条匹配结果
而当stripped时,只有18个匹配结果
但前面也提到,Pigaios的主要目的是低误报率,避免误导分析人员,所以也是一个不错的工具