1. 引言
LibAM 是一个用于第三方库(Third Party Library,TPL)检测的区域匹配框架,该框架将独立的函数连接到函数调用图(Function Call Graph,FCG)上的函数区域(Function Area,FA),并通过比较这些 FA 的相似性来检测 TPL,从而显著减轻不同优化选项和架构的影响。LibAM 的原理图如下图所示。
LibAM 的源代码可从 Github下载,源代码的结构如下图所示。
2. preprocess 代码分析
binary_preprocess_module.getAllFiles(DATA_PATH+"2_target/timecost", DATA_PATH+"1_binary/target", DATA_PATH+"2_target/", mode="1")
binary_preprocess_module.getAllFiles(DATA_PATH+"3_candidate/timecost", DATA_PATH + "1_binary/candidate", DATA_PATH + "3_candidate/", mode="1")
这部分代码使用 IDA Pro 从 Target Binary 和 TPL Binary 中提取 Target ACFG、TPL ACFG、Target FCG、TPL FCG。代码主要调用了 binary_preprocess.py 中的 getAllFiles(),该方法首先根据 filePath 获取二进制文件的路径,之后通过不同参数的 multi_process_extract() 实现二进制文件特征的提取与二进制文件函数调用图的生成。
注:ACFG 是函数粒度的,FCG 是文件粒度的
multi_process_extract() 的主要功能是通过多个进程处理二进制文件,该函数会调用 extract() 以实现二进制文件的处理。
extract() 的主要功能是实现二进制文件特征和函数调用图的提取,该函数的执行依赖于 IDA 指令的执行如下所示。
ida_cmd = 'TVHEADLESS=1 ' + IDA_PATH + ' -L/data/lisiyuan/work2023/code/libAE/libAE_github/libae/idalog.txt -c -A -B -S\'' + idapython + " " + save_name + '\' ' + os.path.join(bpath, bbianry+"_", bbianry)
s, o = subprocess.getstatusoutput(ida_cmd)
在 IDA 指令中特征提取和调用图的提取可由 idapython 对应的 IDA 脚本(ida_get_features.py,ida_get_func_call.py)实现。
3. embedding 代码分析
embeddings_generate_module.subfcg_embedding(DATA_PATH+"4_embedding/timecost",
DATA_PATH+"2_target/feature",
DATA_PATH+"4_embedding/target_in9_bl5_embedding.json",
model_path=WORK_PATH + "/code/embeddings_generate/gnn-best.pt")
embeddings_generate_module.subfcg_embedding(DATA_PATH+"4_embedding/timecost",
DATA_PATH+"3_candidate/feature",
DATA_PATH+"4_embedding/candidate_in9_bl5_embedding.json",
model_path=WORK_PATH + "/code/embeddings_generate/gnn-best.pt")
embeddings_generate_module.generate_afcg(DATA_PATH+"4_embedding/tar_afcg",
os.path.join(DATA_PATH, "2_target/fcg"),
DATA_PATH+"4_embedding/target_in9_embedding.json",
model_path=os.path.join(WORK_PATH, "code/reuse_area_exploration/Embeded-GNN/fcg_gnn-best-0.01.pt"))
embeddings_generate_module.generate_subgraph(DATA_PATH+"4_embedding/tar_subgraph",
os.path.join(DATA_PATH, "2_target/fcg"),
DATA_PATH+"4_embedding/target_in9_embedding.json",
model_path=os.path.join(WORK_PATH, "code/reuse_area_exploration/Embeded-GNN/fcg_gnn-best-0.01.pt"))
embeddings_generate_module.generate_afcg(DATA_PATH+"4_embedding/cdd_afcg",
os.path.join(DATA_PATH, "3_candidate/fcg"),
DATA_PATH+"4_embedding/candidate_in9_embedding.json",
model_path=os.path.join(WORK_PATH, "code/reuse_area_exploration/Embeded-GNN/fcg_gnn-best-0.01.pt"))
embeddings_generate_module.generate_subgraph(DATA_PATH+"4_embedding/cdd_subgraph",
os.path.join(DATA_PATH, "3_candidate/fcg"),
DATA_PATH+"4_embedding/candidate_in9_embedding.json",
model_path=os.path.join(WORK_PATH, "code/reuse_area_exploration/Embeded-GNN/fcg_gnn-best-0.01.pt"))
这部分代码使用 GNN 对 Target ACFG、TPL ACFG、Target FCG、TLP FCG 进行嵌入,生成对应的嵌入向量 V(*)。代码调用了 Generate_func_embedding.py 中的 subfcg_embedding()、generate_afcg()、generate_subgraph()。
subfcg_embedding():加载神经网络模型、遍历测试数据集中的JSON文件,计算每个文件的嵌入特征、记录处理时间并保存嵌入结果、根据条件过滤出特征数量符合要求的数据并生成对应的嵌入。生成 Target ACFG 与 TPL ACFG 的函数嵌入
generate_afcg():创建保存 ACFG 的目录、创建保存 ACFG 的目录、遍历所有函数,检查是否已生成 ACFG、加载对应的 FCG,获取函数的子节点、将生成的 ACFG 保存为 JSON 文件。生成 ACFG 对应的 JSON 文件
generate_subgraph():创建用于保存子图的目录、加载图神经网络模型、读取函数嵌入信息、遍历每个函数,加载相应的控制流图、遍历每个函数加载相应的控制流图、递归地构建子图并计算其嵌入特征、将所有生成的子图存储为 JSON 文件。生成 SUBGRAPH 对应的 JSON 文件
4. func_compare 代码分析
anchor_detection_module.func_compare_annoy_fast_multi(os.path.join(DATA_PATH, "4_embedding/target_in9_embedding.json"),
os.path.join(DATA_PATH, "4_embedding/candidate_in9_embedding.json"),
os.path.join(DATA_PATH, "5_func_compare_result/score"),
os.path.join(DATA_PATH, "5_func_compare_result/score_top50"),
os.path.join(DATA_PATH, "5_func_compare_result"),
os.path.join(DATA_PATH, "5_func_compare_result/embedding_annoy"))
5. tpl_detection 代码分析
save_path = "6_tpl_fast_result/"
anchor_reinforcement_module.tpl_detection_fast_annoy(os.path.join(DATA_PATH, "2_target/fcg"),
os.path.join(DATA_PATH, "3_candidate/fcg"),
os.path.join(DATA_PATH, "5_func_compare_result/score/"),
os.path.join(DATA_PATH, save_path+"tpl_fast_result"),
os.path.join(DATA_PATH, save_path+"tpl_fast_area"),
os.path.join(DATA_PATH, save_path+"tpl_fast_time"),
os.path.join(DATA_PATH, "4_embedding"),
os.path.join(DATA_PATH, save_path+"sim_func_list"),
os.path.join(DATA_PATH, "4_embedding/target_in9_bl5_embedding.json"),
os.path.join(DATA_PATH, "4_embedding/candidate_in9_bl5_embedding.json"),
os.path.join(WORK_PATH, "code/reuse_area_exploration/Embeded-GNN/fcg_gnn-best-0.01.pt"),
DATA_PATH+"4_embedding/tar_afcg",
DATA_PATH+"4_embedding/cdd_afcg",
DATA_PATH+"4_embedding/tar_subgraph",
DATA_PATH+"4_embedding/cdd_subgraph")
TPL_detection_module2.get_result_json(os.path.join(DATA_PATH, save_path+"tpl_fast_result"), os.path.join(DATA_PATH, save_path+"tpl_fast_result.json"))
TPL_detection_module3.cal_libae_result(os.path.join(DATA_PATH, save_path+"tpl_fast_result.json")
6. area_detection 代码分析
if "dataset2" in DATA_PATH:
reuse_area_detection_module.get_area_result_several(os.path.join(DATA_PATH, "7_reuse_detection_result/reuse_detection_area/"),
os.path.join(DATA_PATH, "8_reuse_area_result/reuse_detection_area"),
os.path.join(GT_PATH, "area_ground_truth.json"),
os.path.join(DATA_PATH, "2_target/fcg"),
os.path.join(DATA_PATH, "3_candidate/fcg") )
elif "dataset3" in DATA_PATH:
reuse_area_detection_module.get_area_result_for_each(os.path.join(DATA_PATH, "7_reuse_detection_result/reuse_detection_area/"),
os.path.join(DATA_PATH, "8_reuse_area_result/reuse_detection_area_for_each"),
os.path.join(GT_PATH, "area_ground_truth.json"),
os.path.join(DATA_PATH, "2_target/fcg"),
os.path.join(DATA_PATH, "3_candidate/fcg") )