Bootstrap

论文复现_LibAM: An Area Matching Framework for Detecting Third-Party Libraries in Binaries

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") )   

;