1. 内容概述
前言:此代码库支持 USENIX Security '22 论文 《How Machine Learning Is Solving the Binary Function Similarity Problem》,作者包括 Andrea Marcelli 等人,提供了相关代码、数据集和技术细节。
关键内容:技术报告提供了有关数据集和方法的更多技术细节,供进一步参考。代码库的结构包括以下部分:Binaries(二进制文件),存放已编译的二进制文件及其下载/编译脚本;IDBs(IDA Pro 数据库),存储由 IDA Pro 分析后生成的数据库;DBs(数据集),包含选定函数的数据集、对应的特征以及生成脚本;IDA_scripts(IDA Pro 脚本),用于特征提取的脚本;Models(模型),实现了多种机器学习方法的代码;Results(结果),提供实验结果和提取指标的相关脚本。
使用场景:使用场景包括三种主要方式。复现实验,通过利用 DBs
和 Models
中的现有数据集与模型,按照提供的脚本和 README 文件复现实验结果;测试新方法,使用现有的特征提取和处理工具,在现有数据集上评估新方法的表现;推理新函数,通过 Models
文件夹中的推理工作流,结合 IDA Pro 脚本提取特征,并使用后处理脚本转换数据格式。
2. 二进制文件(Binary)
要下载二进制文件,首先确保系统有大约 15GB 的空闲磁盘空间。然后,可以通过 Google Drive 下载二进制文件,使用 gdrive_download.py
Python3 脚本,按照以下步骤操作:
# 安装 Python3 的 virtualenv 环境管理工具:
pip install virtualenv
# 创建一个新的虚拟环境并安装所需的依赖包:
python3 -m venv ../env
source ../env/bin/activate
pip install -r ../requirements.txt
# 下载并解压二进制文件:
python3 ../gdrive_download.py --binaries
# 二进制文件将被解压到以下目录:
Binaries/Dataset-Vulnerability
Binaries/Dataset-1
Binaries/Dataset-2
如果希望从源代码编译二进制文件,可以参考 Dataset-1
的交叉编译说明,见 [编译脚本](Compilation scripts) 文件夹。Dataset-2
和 Dataset-Vulnerability
的二进制文件是 Trex 发布的子集,相关原始数据集可从 此链接 获取。
此文件夹包含编译Dataset-1二进制文件所需的文档和脚本。二进制文件在Ubuntu 18.04和19.04环境中编译,部分编译器工具链由于缺少所需版本而手动编译。编译过程包括设置环境、安装必要的软件包、下载源码、应用补丁和运行自动化编译脚本。支持的架构包括x86、x64、ARM32、ARM64、MIPS32和MIPS64,不同架构使用的编译器版本和配置有所不同。提供了对每种架构的具体配置说明和编译过程中遇到的一些常见问题及解决方法。
3. IDA PRO 数据库(DBs)
该目录包含用于评估不同测试用例中相似度方法的数据集,每个数据集包含选定的函数、相应的特征以及生成它们的脚本。数据集按用途和测试对象组织,包括:Dataset-1,用于训练、验证和测试相似度方法;Dataset-1-CodeCMR,作为Dataset-1的子集,专门用于测试CodeCMR/BinaryAI方法;Dataset-2,用于测试的另一个数据集;以及Dataset-Vulnerability,用于评估相似度方法在“漏洞搜索”测试用例中的效果。
3.1 数据集下载
# 安装Python3的虚拟环境,并激活:
python3 -m venv ../env
source ../env/bin/activate
pip install -r ../requirements.txt
# 使用gdrive_download.py脚本从Google Drive下载并解压特征文件:
python3 ../gdrive_download.py --features
# 下载后的特征将解压到以下目录:
DBs/Dataset-1/
DBs/Dataset-1-CodeCMR/
DBs/Dataset-2/
DBs/Dataset-Vulnerability/
3.2 Dataset-1 介绍
#包含生成数据集和提取特征的说明文件。主要文件和子文件夹如下:
Dataset-1
├── Dataset-1 creation.ipynb: 创建数据集
├── Dataset-1 plots.ipynb: 展示数据集组成
├── Dataset-1 sanity check.ipynb: 验证数据完整性
├── features
│ ├── flowchart_Dataset-1.csv: 包括至少 5 个基本块的函数列表
│ ├── testing
│ │ ├── acfg_disasm_Dataset-1_testing: 通过 IDA 插件提取的特征文件
│ │ ├── acfg_features_Dataset-1_testing: 通过 IDA 插件提取的特征文件
│ │ ├── fss_Dataset-1_testing
│ │ ├── selected_testing_Dataset-1.json
│ │ └── zeek_Dataset-1_testing.json
│ ├── training
│ └── validation
├── pairs
└── testing_Dataset-1.csv
3.3 Dataset-1-CodeCMR 介绍
Dataset-1-CodeCMR是专门用于测试CodeCMR/BinaryAI方法的数据集,其结构与Dataset-1类似。主要包括Dataset-1-CodeCMR creation.ipynb
(用于重建数据集)、Dataset-1-CodeCMR example.ipynb
(展示如何使用数据)以及多个features/*
文件,这些文件包含通过IDA插件提取的特征。
3.4 Dataset-2 介绍
用于测试的第二个数据集(Dataset-2)结构与Dataset-1相似,包含不同的特征文件。其主要包括`Dataset-2 creation.ipynb`(用于重建数据集)和多个`features/*`文件,这些特征文件通过IDA插件提取,涵盖了不同的特征类型,如ACFG、Catalog1、FSS等。
3.5 Dataset-Vulnerability
Dataset-Vulnerability用于评估相似度方法在“漏洞搜索”测试中的效果,结构与其他数据集类似。主要包括Dataset-Vulnerability creation.ipynb
(用于重建数据集)和多个features/*
文件,这些文件包含通过IDA插件提取的特征。
4. IDA PRO 脚本(IDA_script)
该文件夹包含一个脚本,用于从已编译的二进制文件生成 IDBs(IDA 数据库),以及若干 IDA Pro 插件,用于特征提取。
4.1 系统要求
# 设置 IDA32_PATH 和 IDA_PATH 环境变量,指定 idat 和 idat64 的完整路径。例如:
export IDA_PATH=/home/user/idapro-7.3/idat64
export IDA32_PATH=/home/user/idapro-7.3/idat
# 创建名为 "env" 的新环境
python3 -m venv env
# 进入虚拟环境
source env/bin/activate
# 在当前环境中安装所需的包
pip install -r requirements.txt
# 在 IDA Pro Python2 环境 中安装 Capstone 3.0.4:
pip2 install capstone==3.0.4
# 在 IDA Pro Python3 环境 中安装 networkx 2.5:
pip3 install networkx==2.5
# 导出用于 IDA 插件单元测试的 IDBs:
python3 generate_idbs.py --test
4.2 生成 IDBs
使用 generate_idbs.py
脚本可以自动导出每个数据集的 IDBs,输入为用于处理的数据集对应的标志(如 --db1
、--db2
、--dbvuln
),输出为相应的 IDBs 和日志文(generate_idbs_log.txt
)。
# 为 Dataset-Vulnerability 生成 IDBs(该数据集最小,仅包含六个二进制文件):
python3 generate_idbs.py --dbvuln
# 为 Binaries 文件夹中的所有二进制文件生成 IDBs(此过程可能需要数小时并占用数 GB 的磁盘空间):
python3 generate_idbs.py --db1 --db2 --dbvuln
4.4 IDA FlowChart
该插件提取每个函数的基本信息,要求函数至少包含五个基本块。输入为包含 IDB 文件的文件夹(-i)和输出 CSV 文件的名称(-o),输出为一个 CSV 文件,包含所有至少有五个基本块的函数。
# 运行插件处理 Dataset-Vulnerability 的 IDBs(要求 IDBs 存放在 IDBs/Dataset-Vulnerability 目录下):
cd IDA_flowchart
python3 cli_flowchart.py -i ../../IDBs/Dataset-Vulnerability -o flowchart_Dataset-Vulnerability.csv
# 运行单元测试:
python3 -m unittest test_flowchart.py
# 可选 - 测试多个文件
python3 -m unittest test_large_flowchart.py
4.5 IDA ACFG-disasm
该插件为每个选择的函数创建一个带有基本块反汇编的 ACFG。输入为包含选定函数的 JSON 文件(-j)和输出文件夹的名称(-o),输出为每个 IDB 生成一个 JSON 文件(_acfg_disasm.json)。注意,输入 JSON 中的 IDB 文件路径必须是相对路径,Python3 脚本会将其转换为完整路径,以便正确加载 IDB 文件。
# 运行插件处理 Dataset-Vulnerability 测试选定的函数(要求 IDBs 存放在 IDBs/Dataset-Vulnerability 目录下):
cd IDA_acfg_disasm
python3 cli_acfg_disasm.py -j ../../DBs/Dataset-Vulnerability/features/selected_Dataset-Vulnerability.json -o acfg_disasm_Dataset-Vulnerability
# 运行单元测试:
python3 -m unittest test_acfg_disasm.py
# 可选 - 测试多个文件
python3 -m unittest test_large_acfg_disasm.py
4.6 IDA ACFG-features
该插件为每个选择的函数创建一个带有 Genius/Gemini 特征的 ACFG。输入为包含选定函数的 JSON 文件(-j)和输出文件夹的名称(-o),输出为每个 IDB 生成一个 JSON 文件(_acfg_features.json)。注意,输入 JSON 中的 IDB 文件路径必须是相对路径,Python3 脚本会将其转换为完整路径,以便正确加载 IDB 文件。
# 运行插件处理 Dataset-Vulnerability 测试选定的函数(要求 IDBs 存放在 IDBs/Dataset-Vulnerability 目录下):
cd IDA_acfg_features
python3 cli_acfg_features.py -j ../../DBs/Dataset-Vulnerability/features/selected_Dataset-Vulnerability.json -o acfg_features_Dataset-Vulnerability
# 运行单元测试:
python3 -m unittest test_acfg_features.py
# 可选 - 测试多个文件
python3 -m unittest test_large_acfg_features.py
5. 模型(Models)
该目录包含了经过测试的多个方法的代码,包括:Asm2vec 和 Doc2vec、BinaryAI / CodeCMR、Catalog1、FunctionSimSearch、GGSNN 和 GMN、GNN-s2v、SAFE、Trex 和 Zeek。
5.1 Asm2vec
Asm2vec 和 Doc2vec 实现由两个部分组成。第一部分接受ACFG disasm数据作为输入,并生成选定函数的随机游走。然后,这些数据作为第二部分的输入,后者实现了机器学习组件。
5.1.1 Part 1
Asm2vec 工具的第一部分是通过一个名为 i2v_preprocessing.py 的 Python3 脚本实现的。我们还提供了一个带有所需依赖项的 Docker 容器。
输入是通过 ACFG disasm IDA 插件提取的 JSON 文件所在的文件夹:
- 对于我们发布的 数据集,JSON 文件已经在 features 目录中提供。请注意,特征可以通过 README 中的说明从 GDrive 下载。
- 要为新的二进制文件集提取特征,请按照 README 中的说明运行 ACFG disasm IDA 插件。
有许多可配置参数,例如:
- -a2v 或 -d2v,指定输出是否与 Asm2vec 或 Doc2vec(PV-DM 或 PV-DBOW)模型兼容
- --num_rwalks、--max_walk_len 和 --max_walk_tokens 用于配置每个随机游走的数量和长度
- --min_frequency 是选择 token 的最小出现次数
- --workers 定义并行进程的数量:数量越高越好,但取决于 CPU 核心数。
该脚本将生成以下输出文件夹:
- 一个名为 random_walks_{model}.csv 的文件,其中包含选定函数的随机游走
- 一个名为 vocabulary.csv 的文件,包含用于训练神经网络的 token 列表
- 一个名为 counter_dict.json 的文件,映射每个 token 的频率计数
- 一个名为 vocabulary_dropped.csv 的文件,包含在分析中丢弃的低频 token 列表
- 一个名为 id2func.json 的文件,映射每个选定函数到一个数字 ID
- 一个名为 i2v_preprocessing.log 的文件,包含分析的日志,可能对调试有帮助。
使用 Docker 的操作步骤:
# 构建 Docker 镜像:
docker build -t asm2vec .
# 在 Docker 容器中运行 i2v_preprocessing.py 脚本:
docker run --rm -v <path_to_the_acfg_disasm_dir>:/input -v <path_to_the_output_dir>:/output -it asm2vec /code/i2v_preprocessing.py -d [--workers 4] [-a2v, -d2v] -i /input -o /output/
# 可以使用以下命令查看所有命令行选项:
docker run --rm -it asm2vec /code/i2v_preprocessing.py --help
# 为数据集 1 的训练部分运行 i2v_preprocessing.py 脚本并使用 -a2v:
docker run --rm -v $(pwd)/../../DBs/Dataset-1/features/training/acfg_disasm_Dataset-1_training:/input -v $(pwd):/output -it asm2vec /code/i2v_preprocessing.py -d -w4 -a2v -i /input -o /output/a2v_preprocessing_Dataset-1-training
# 为数据集 1 的训练部分运行 i2v_preprocessing.py 脚本并使用 -d2v:
docker run --rm -v $(pwd)/../../DBs/Dataset-1/features/training/acfg_disasm_Dataset-1_training:/input -v $(pwd):/output -it asm2vec /code/i2v_preprocessing.py -d -w4 -d2v -i /input -o /output/d2v_preprocessing_Dataset-1-training
# 为数据集 1 的测试部分运行 i2v_preprocessing.py 脚本并使用 -a2v:
docker run --rm -v $(pwd)/../../DBs/Dataset-1/features/testing/acfg_disasm_Dataset-1_testing:/input -v $(pwd)/a2v_preprocessing_Dataset-1-training:/training_data -v $(pwd):/output -it asm2vec /code/i2v_preprocessing.py -d -w4 -a2v -i /input -v /training_data/vocabulary.csv -o /output/a2v_preprocessing_Dataset-1-testing
5.1.2 Part 2
Asm2vec 的机器学习组件是基于 Gensim 3.8 实现的。有关实现的详细信息,请参阅我们创建的 补丁。i2v.py 脚本用于运行 Asm2vec 和 Doc2vec(PV-DM 或 PV-DBOW)模型的训练和推理。第一部分的 Docker 容器也包含了神经网络部分所需的依赖项。
i2v.py 脚本的 输入 包括:
- i2v_preprocessing.py 的输出,包含选择的词汇、随机游走和 token 的频率。
- {model}_checkpoint(仅在推理模式下使用,即在验证和测试期间)。
有许多可配置的参数,例如:
- 使用 --pvdm、--pvdbow 或 --asm2vec 选项选择要使用的模型(训练和推理时必须相同)
- 选择 --train 或 --inference 模式
- 通过 --epochs 参数配置训练的周期数
- 使用 --workers 选项选择并行进程的数量。
i2v.py 脚本中还包含一些硬编码的参数,标记为 # FIXED PARAM。不同参数值的实验需要进一步研究。当在训练模式下运行时,模型将生成以下 输出:
- 一个名为 {model}_checkpoint 的文件,包含训练后的模型备份。这可以在推理时重新使用
- 一个名为 i2v.log 的文件,包含分析日志,可能对调试有帮助。
当在 推理模式 下运行时,模型将生成以下 输出:
- 一个名为 embeddings.csv 的 CSV 文件,包含模型为每个函数生成的嵌入
- 一个名为 i2v.log 的文件,包含分析日志,可能对调试有帮助。
注意:在推理时,Asm2vec 和 Doc2vec 模型需要在多个周期内 更新 内部权重(类似于训练时的操作)。不过,只更新与函数对应的矩阵,而 token 的矩阵保持固定。与其他 传统 机器学习模型的行为不同。
使用 Docker 的操作步骤:
# 运行神经网络模型
docker run --rm -v <path_to_i2v_preprocessing_output_folder>:/input -v $(pwd):/output -it asm2vec /code/i2v.py -d [--asm2vec, --pvdm, --pvdbow] [--train, --inference, --log] -e1 -w4 --inputdir /input/ -o /output/output_folder
# 使用以下命令查看所有命令行选项:
docker run --rm -it asm2vec /code/i2v.py --help
# 在数据集 1 上训练 Asm2vec 模型:
docker run --rm -v $(pwd)/a2v_preprocessing_Dataset-1-training:/input -v $(pwd):/output -it asm2vec /code/i2v.py -d --asm2vec --train -e1 -w4 --inputdir /input/ -o /output/asm2vec_train_Dataset-1-training
# 在数据集 1 的测试数据上运行 Asm2vec 模型并进行推理:
docker run --rm -v $(pwd)/a2v_preprocessing_Dataset-1-testing:/input -v $(pwd)/asm2vec_train
5.2 Catalog1
Catalog1实验需要运行一个IDA Pro插件来提取二进制函数的MinHash签名。
# 编译Catalog1库:
(cd catalog1/; make)
IDA Pro插件的输入是包含所选函数的JSON文件(-j)以及输出的CSV文件名称(-o),输出为每个Catalog1签名大小对应的CSV文件(默认:[16, 32, 64, 128])。需要注意的是,输入JSON中的IDB文件路径必须相对于binary_function_similarity目录,Python3脚本会将相对路径转换为完整路径,以确保IDA Pro能够正确加载IDB。
# 对Dataset-Vulnerability测试中的选定函数运行插件(需要将IDBs放在IDBs/Dataset-Vulnerability目录中)
python3 cli_catalog1.py -j ../../DBs/Dataset-Vulnerability/features/selected_Dataset-Vulnerability.json -o Dataset-Vulnerability_catalog1.csv
# 运行单元测试:
python3 -m unittest test_catalog1.py
# 可选 - 对多个文件进行测试
python3 -m unittest test_large_catalog1.py
插件将生成一组CSV文件,包含以下列:path
(IDB路径)、address
(函数地址)、size
(函数大小)、catalog_hash_list
(Catalog哈希值,使用分号;
分隔)以及time
(计算函数Catalog1哈希所需的时间)。
# 要计算两个Catalog1签名之间的相似度,可以使用Jaccard相似度,如下所示:
def jaccard_similarity(s1, s2):
return len(set(s1) & set(s2)) / len(set(s1) | set(s2))
a = [10534612, 42437122, 187632428, 38160894, 167893582, 20517613, 328764745, 40669729]
b = [15508139, 42437122, 83784247, 138119612, 167793573, 29886129, 35551260, 1210122]
print(jaccard_similarity(a, b)) # 0.06666666666666667
print(jaccard_similarity(a, a)) # 1.0
注意:如果函数大小小于4字节,
catalog_hash_list
列中将插入min_function_size_error
。
# Catalog1实现了MinHash算法,库可以用于对任何二进制数据流计算签名:
from catalog1.catalog_fast import sign
from catalog1.catalog_slow import slow_sign
SIG_SIZE = 128 # 示例值:16, 32, 64, 128
binary_data = "..."
# C实现(快速)
signature = sign(binary_data, SIG_SIZE)
# Python3实现
signature_slow = slow_sign(binary_data, SIG_SIZE)
5.3 CodeCMR
BinaryAI / CodeCMR实验包括两个步骤。第一步是一个IDA Pro插件,它接受一个JSON文件作为输入,指定需要进行测试的函数,输出结果为pickle格式的中间文件。第二步是训练一个神经网络,用于识别相似函数。神经网络的输出是每个函数的向量表示。
在运行IDA插件之前,请按照IDA_scripts README中的要求操作。插件的输入为包含所选函数的JSON文件(`-j`)和输出目录(`-o`),输出为每个IDB对应的pickle文件,文件中包含每个在IDB中分析的函数的特征提取后的NetworkX图的序列化版本。需要注意,插件要求IDA Pro反编译许可证,并且IDA Pro要求32位IDA用于反编译32位二进制文件,64位IDA用于反编译64位二进制文件。32位二进制文件需导出为`.idb`格式,64位二进制文件需导出为`.i64`格式。此外,输入JSON中的IDB文件路径必须相对于`binary_function_similarity`目录,Python3脚本会将相对路径转换为完整路径,以确保在IDA Pro中正确加载IDB。示例:对Dataset-1-CodeCMR测试所选函数运行插件(需要64位二进制的`.i64` IDBs和32位二进制的`.idb`)。
# 对Dataset-1-CodeCMR测试所选函数运行插件(需要64位二进制的.i64 IDBs和32位二进制的.idb):
cd IDA_CodeCMR
python3 cli_codeCMR.py -j ../../../DBs/Dataset-1-CodeCMR/features/selected_Dataset-1-CodeCMR.json -o Dataset-1-CodeCMR
# 运行单元测试:
python3 -m unittest test_codeCMR.py
5.4 functionsimsearch
FSS(函数相似性搜索)实验包括两个步骤:第一步是IDA Pro插件,接受一个JSON文件作为输入,指定要分析的函数,并输出中间结果为JSON格式;第二步接收第一步生成的JSON文件,输出四个CSV文件,每个文件包含特定配置下的实验结果。该工具基于Thomas Dullien的FunctionSimSearch项目,我们在此基础上派生了代码,并根据需求进行了定制,整合了分析层并调整了Docker容器,具体修改记录在functionsimsearch.patch
文件中。
5.4.1 Part 1
在运行IDA插件之前,请按照IDA_scripts README中的要求操作。输入包括包含所选函数的JSON文件(-j)、输出目录(-o)以及(-c)使用Capstone进行反汇编。输出为每个IDB对应一个JSON文件。需要注意的是,输入JSON中的IDB文件路径必须相对于binary_function_similarity
目录,Python3脚本会将相对路径转换为完整路径,以确保在IDA Pro中正确加载IDB。
# 对Dataset-Vulnerability测试所选函数运行插件(需要在IDBs/Dataset-Vulnerability目录中的IDB文件)
cd IDA_fss
python3 cli_fss.py -j ../../../DBs/Dataset-Vulnerability/features/selected_Dataset-Vulnerability.json -o fss_Dataset-Vulnerability -c
# 运行单元测试:
python3 -m unittest test_fss.py
# 可选 - 多文件测试
python3 -m unittest test_large_fss.py
5.4.2 Part 2
输入为通过IDA_fss插件生成的JSON文件目录,输出为四个CSV文件,每个文件包含一个特定配置的实验结果。
构建并允许Docker容器:
# 克隆functionsimsearch仓库并应用补丁:
git clone https://github.com/googleprojectzero/functionsimsearch;
( cd functionsimsearch ; git checkout ec5d9e1224ff915b3dc9e7af19e21e110c25239c ; patch -s -p0 < ../functionsimsearch.patch );
cp fss_simhasher.py ./functionsimsearch/;
# 构建Docker镜像:
docker build -t fss ./functionsimsearch
# 在Docker容器内运行主脚本:
docker run --rm -it fss -v <完整路径-to-输入JSON目录>:/input -v <完整路径-to-输出CSV目录>:/output /fss_simhasher.py
# 在/tmp/fss_csvs中创建四个CSV文件:
docker run --rm -v $(pwd)/testdata/fss_jsons:/input -v /tmp/fss_csvs:/output -it fss /fss_simhasher.py
# 为Dataset-2运行脚本:
docker run --rm -v $(pwd)/../../DBs/Dataset-2/features/fss_Dataset-2:/input -v $(pwd)/../../Results/FunctionSimSearch/Dataset-2:/output -it fss /fss_simhasher.py
5.5 GGSNN-GMN
该文件夹包含了DeepMind的GGSNN和GMN模型的实现。工具由两个部分组成,第一部分接受ACFG disasm数据作为输入,并生成若干中间结果,这些结果将作为第二部分的输入,第二部分实现了机器学习组件。
5.5.1 Part 1
第一部分的工具通过一个名为gnn_preprocessing.py的Python3脚本实现。我们还提供了一个包含所需依赖的Docker容器。
输入:通过ACFG disasm IDA插件提取的JSON文件所在的文件夹:
- 对于我们发布的数据集,JSON文件已经存储在features目录下。请注意,特征文件可以通过GDrive下载,具体操作参见README。
- 要提取新二进制文件的特征,请按照README中的说明运行ACFG disasm IDA插件。
- 一个JSON文件opcodes_dict.json,用于将所选操作码映射到训练数据集中的频率排名。
该脚本将生成以下输出:
- 一个JSON文件opcodes_dict.json,将所选操作码映射到训练数据集中的频率排名(仅在--training模式下运行时生成)。
- 一个JSON文件graph_func_dict_opc_{}.json,包含所选的中间特征。
使用Docker的说明:
# 构建docker镜像:
docker build --no-cache Preprocessing/ -t gnn-preprocessing
# 在docker容器中运行主脚本:
docker run --rm \
-v <path_to_the_acfg_disasm_dir>:/input \
-v <path_to_the_training_data>:/training_data \
-v <path_to_the_output_dir>:/output \
-it gnn-preprocessing /code/gnn_preprocessing.py -i /input [--training] -o /output
# 通过以下命令查看gnn_preprocessing.py的所有选项:
docker run --rm -it gnn-preprocessing /code/gnn_preprocessing.py --help
# 在训练模式下运行gnn_preprocessing.py,针对Dataset-1_training:
docker run --rm \
-v $(pwd)/../../DBs/Dataset-1/features/training/acfg_disasm_Dataset-1_training:/input \
-v $(pwd)/Preprocessing/Dataset-1_training:/output \
-it gnn-preprocessing /code/gnn_preprocessing.py -i /input --training -o /output
# 在Dataset-1_validation上运行gnn_preprocessing.py:
docker run --rm \
-v $(pwd)/../../DBs/Dataset-1/features/validation/acfg_disasm_Dataset-1_validation:/input \
-v $(pwd)/Preprocessing/Dataset-1_training:/training_data \
-v $(pwd)/Preprocessing/Dataset-1_validation:/output \
-it gnn-preprocessing /code/gnn_preprocessing.py -i /input -d /training_data/opcodes_dict.json -o /output
# 运行单元测试:
docker run --rm \
-v $(pwd)/Preprocessing/testdata/:/input \
-v $(pwd)/Preprocessing/testdata/gnn_intermediate:/output \
-it gnn-preprocessing /bin/bash -c "( cd /code && python3 -m unittest test_gnn_preprocessing.py )"
5.5.2 Part 2
第二部分实现了机器学习组件。我们还提供了一个包含TensorFlow 1.14和其他所需依赖的Docker容器。神经网络模型的输入:
- 用于训练的CSV文件,或者用于验证和测试的函数对。这些文件在我们发布的数据集中已经提供。文件路径在config.py文件中根据数据集类型硬编码。
- 来自第一部分的graph_func_dict_opc_{}.json文件。
- 如果模型在推理模式下使用(即在验证和测试时),则需要提供模型的检查点。
模型将生成以下输出:
- 一组包含选定函数相似度(sim列)的CSV文件,用于验证和测试。
- 一个config.json文件,记录运行测试时使用的配置。该文件用于调试和追踪不同的实验。
- 一个gnn.log日志文件,记录神经网络的日志。可以通过使用--debug (-d)选项来改善日志记录。
- 如果模型正在训练,则会生成模型检查点。
使用Docker的说明:
# 构建docker镜像:
docker build --no-cache NeuralNetwork/ -t gnn-neuralnetwork
# 在Docker容器中运行神经网络:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/Preprocessing:/preprocessing \
-v $(pwd)/NeuralNetwork/:/output \
-it gnn-neuralnetwork /code/gnn.py (--train | --validate | --test) [--num_epochs 10] \
--model_type {embedding, matching} --training_mode {pair,triplet} \
--features_type {opc,nofeatures} --dataset {one,two,vuln} \
-c /code/model_checkpoint \
-o /output/Dataset-x
# 通过以下命令查看gnn.py的所有选项:
docker run --rm -it gnn-neuralnetwork /code/gnn.py --help
# 针对Dataset-1进行GGSNN模型(embedding)训练,使用opc特征和pair模式:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/NeuralNetwork:/output \
-v $(pwd)/Preprocessing:/preprocessing \
-it gnn-neuralnetwork /code/gnn.py --train --num_epochs 10 \
--model_type embedding --training_mode pair \
--features_type opc --dataset one \
-c /output/model_checkpoint_$(date +'%Y-%m-%d') \
-o /output/Dataset-1_training_GGSNN_opc_pair
# 针对Dataset-1进行GMN模型(matching)训练,使用opc特征和pair模式:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/NeuralNetwork:/output \
-v $(pwd)/Preprocessing:/preprocessing \
-it gnn-neuralnetwork /code/gnn.py --train --num_epochs 16 \
--model_type matching --training_mode pair \
--features_type opc --dataset one \
-c /output/model_checkpoint_$(date +'%Y-%m-%d') \
-o /output/Dataset-1_training_GMN_opc_pair
5.6 GNN-s2v
此文件夹包含基于图神经网络(GNN)和Structure2vec(s2v)方法的实现。代码分为两个部分:第一部分以ACFG disasm或ACFG特征数据为输入,生成一系列中间结果,然后将这些结果作为输入传递给第二部分,后者实现了机器学习组件。
下载模型数据:
# 激活Python3虚拟环境
source ../../env/bin/activate
# 下载并解压模型数据到相应目录:
python3 gdrive_model_download.py
# 数据将解压到以下目录:
Pretraining/Dataset-1_training
NeuralNetwork/model_checkpoint_annotations_none_epoch5
NeuralNetwork/model_checkpoint_annotations_numerical_epoch5
5.6.1 Part 1
第一部分实现了两个Python3脚本的预处理步骤,分别是digraph_instructions_embeddings.py和digraph_numerical_features.py。我们还提供了一个带有所需依赖项的Docker容器。
针对《Investigating Graph Embedding Neural Networks with Unsupervised Features Extraction for Binary Analysis》模型的预处理。
为了提取此ML模型所需的特征,请使用digraph_instructions_embeddings.py Python3脚本。
输入:digraph_instructions_embeddings.py的输入是通过ACFG disasm IDA插件提取的JSON文件和预训练的指令嵌入:
- 对于我们发布的数据集,JSON文件已包含在features目录中。请注意,特征可以按照README中的说明从GDrive下载。
- 如果需要为新的二进制文件集提取特征,请按照README中的说明运行ACFG disasm IDA插件。
- 在Pretraining文件夹中,我们提供了汇编指令的词汇表和预训练的指令嵌入。这些嵌入与SAFE模型中使用的嵌入相同,并且是基于Dataset-1的训练部分预训练的。更多信息可以在SAFE README中找到。
- 默认情况下,digraph_instructions_embeddings.py为每个基本块选择前200条指令,但此数量可以通过命令行进行配置。
该脚本将生成以下输出:
- 一个名为digraph_instructions_embeddings_{NUM_INSTRUCTIONS}.json的文件,包含每个选定函数的图表示和特征。
- 一个名为log_coverage.txt的日志文件,提供有关未知指令频率的信息。
针对《Neural network-based graph embedding for cross-platform binary code similarity detection》模型的预处理
为了提取此ML模型所需的特征,请使用digraph_numerical_features.py Python3脚本。
输入:digraph_numerical_features.py的输入是通过ACFG features IDA插件提取的JSON文件:
- 对于我们发布的数据集,JSON文件已包含在features目录中。请注意,特征可以按照README中的说明从GDrive下载。
- 如果需要为新的二进制文件集提取特征,请按照README中的说明运行ACFG features IDA插件。
该脚本将生成以下输出:
- 一个名为digraph_numerical_features.json的文件,包含每个选定函数的图表示和特征。
使用Docker的说明:
# 构建Docker镜像:
docker build Preprocessing/ -t gnn-s2v-preprocessing
# 在Docker容器中运行两个脚本:
docker run \
--rm \
-v <path_to_the_acfg_disasm_dir>:/input \
-v <path_to_the_instruction_embeddings_dir>:/instruction_embeddings \
-v <path_to_the_output_dir>:/output \
-it gnn-s2v-preprocessing /code/digraph_instructions_embeddings.py \
-i /input \
-d /instruction_embeddings/ins2id.json \
-o /output/
docker run \
--rm \
-v <path_to_the_acfg_features_dir>:/input \
-v <path_to_the_output_dir>:/output \
-it gnn-s2v-preprocessing /code/digraph_numerical_features.py \
-i /input \
-o /output
# 使用以下命令查看两个脚本的所有选项:
docker run --rm -it gnn-s2v-preprocessing /code/digraph_instructions_embeddings.py --help
docker run --rm -it gnn-s2v-preprocessing /code/digraph_numerical_features.py --help
# 在Dataset-Vulnerability上运行digraph_instructions_embeddings.py:
docker run \
--rm \
-v $(pwd)/../../DBs/Dataset-Vulnerability/features/acfg_disasm_Dataset-Vulnerability:/input \
-v $(pwd)/Pretraining/Dataset-1_training/:/instruction_embeddings \
-v $(pwd)/Preprocessing/:/output \
-it gnn-s2v-preprocessing /code/digraph_instructions_embeddings.py \
-i /input \
-d /instruction_embeddings/ins2id.json \
-o /output/Dataset-Vulnerability/
# 在Dataset-Vulnerability上运行digraph_numerical_features.py:
docker run \
--rm \
-v $(pwd)/../../DBs/Dataset-Vulnerability/features/acfg_features_Dataset-Vulnerability:/input \
-v $(pwd)/Preprocessing/:/output \
-it gnn-s2v-preprocessing /code/digraph_numerical_features.py \
-i /input \
-o /output/Dataset-Vulnerability/
# 运行单元测试:
docker run \
--rm \
-v $(pwd)/Preprocessing/testdata/:/input \
-v $(pwd)/Pretraining/Dataset-1_training/:/instruction_embeddings \
-v $(pwd)/Preprocessing/testdata/s2v_temp:/output \
-it gnn-s2v-preprocessing /bin/bash \
-c "( cd /code && python3 -m unittest test_digraph_instructions_embeddings.py )"
docker run \
--rm \
-v $(pwd)/Preprocessing/testdata/:/input \
-v $(pwd)/Preprocessing/testdata/s2v_temp:/output \
-it gnn-s2v-preprocessing /bin/bash \
-c "( cd /code && python3 -m unittest test_digraph_numerical_features.py )"
5.6.2 Part 2
第二部分实现了GNN-s2v方法的机器学习组件。我们还提供了一个带有TensorFlow 1.14和其他所需依赖项的Docker容器。
神经网络模型的输入:
- 用于训练的函数的CSV文件,或用于验证和测试的函数对。这些文件在我们发布的数据集中已经存在。文件路径在config.py文件中硬编码,基于数据集类型。
- 嵌入矩阵embeddings.npy,这是与SAFE模型中使用的相同的预训练指令嵌入。可以按照“下载模型数据”中的说明从GDrive下载。
- 第一部分输出的JSON文件(例如digraph_instructions_embeddings_200.json或digraph_numerical_features.json)。
- 模型检查点(仅在模型处于推理模式下使用,即在验证和测试过程中)。
该模型将生成以下输出:
- 一组包含相似度(列sim)的CSV文件,用于验证和测试中选定的函数。
- 一个config.json文件,其中包含用于运行测试的配置。这包括参数和CSV、JSON文件的路径。该文件对于调试和跟踪不同实验非常有用。
- 一个s2v.log日志文件,记录神经网络的日志。为改善日志记录,可以使用--debug(-d)选项。
- 模型检查点(仅在训练模型时生成)。
使用Docker的说明:
# 构建Docker镜像:
docker build NeuralNetwork/ -t gnn-s2v-neuralnetwork
# 在Docker容器中运行神经网络模型:
docker run \
--rm \
-v $(pwd)/Preprocessing:/input \
-v $(pwd)/NeuralNetwork:/output \
-it gnn-s2v-neuralnetwork /bin/bash \
-c "(cd /code && python3 train_model.py --config /input/config.json)"
# run the training on the Dataset-1:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/Pretraining/Dataset-1_training:/instruction_embeddings \
-v $(pwd)/Preprocessing:/preprocessing \
-v $(pwd)/NeuralNetwork/:/output \
-it gnn-s2v-neuralnetwork /code/s2v.py \
--train \
--network_type annotations \
--features_type numerical \
--num_epochs 5 \
--dataset one \
-c /output/model_checkpoint_$(date +'%Y-%m-%d') \
-o /output/Dataset-1_training
# run the validation on Dataset-1 using the model_checkpoint that we trained on Dataset-1:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/Pretraining/Dataset-1_training:/instruction_embeddings \
-v $(pwd)/Preprocessing:/preprocessing \
-v $(pwd)/NeuralNetwork/:/output \
-it gnn-s2v-neuralnetwork /code/s2v.py \
--validate \
--network_type annotations \
--features_type numerical \
--dataset one \
-c /code/model_checkpoint_annotations_numerical_epoch5/ \
-o /output/Dataset-1_validation
# run the testing on Dataset-1 using the model_checkpoint that we trained on Dataset-1:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/Pretraining/Dataset-1_training:/instruction_embeddings \
-v $(pwd)/Preprocessing:/preprocessing \
-v $(pwd)/NeuralNetwork/:/output \
-it gnn-s2v-neuralnetwork /code/s2v.py \
--test \
--network_type annotations \
--features_type numerical \
--dataset one \
-c /code/model_checkpoint_annotations_numerical_epoch5/ \
-o /output/Dataset-1_testing
# run the testing on Dataset-2 using the model_checkpoint that we trained on Dataset-1:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/Pretraining/Dataset-1_training:/instruction_embeddings \
-v $(pwd)/Preprocessing:/preprocessing \
-v $(pwd)/NeuralNetwork/:/output \
-it gnn-s2v-neuralnetwork /code/s2v.py \
--test \
--network_type annotations \
--features_type numerical \
--dataset two \
-c /code/model_checkpoint_annotations_numerical_epoch5/ \
-o /output/Dataset-2_testing
# run the testing on Dataset-Vulnerability using the model_checkpoint that we trained on Dataset-1:
docker run --rm \
-v $(pwd)/../../DBs:/input \
-v $(pwd)/Pretraining/Dataset-1_training:/instruction_embeddings \
-v $(pwd)/Preprocessing:/preprocessing \
-v $(pwd)/NeuralNetwork/:/output \
-it gnn-s2v-neuralnetwork /code/s2v.py \
--test \
--network_type annotations \
--features_type numerical \
--dataset vuln \
-c /code/model_checkpoint_annotations_numerical_epoch5/ \
-o /output/Dataset-Vulnerability_testing