- 人工智能
- 大模型
- 逆向工程
- 微调
- 代码模型
【免费下载链接】LLM4Decompile
Reverse Engineering: Decompiling Binary Code with Large Language Models
LLM4Decompile 是面向“用大语言模型将二进制代码反编译为可读 C 源码”的开源项目,evaluation/README.md 集中说明了其官方评估流程:推荐用 vLLM 批量生成反编译结果,再通过“编译 + 运行 + 断言”的方式统计可再执行率(Re-executability)。本文以该文档为主干,结合evaluation/目录下的三个评测脚本与scripts/目录的启动脚本,逐项讲解测试集的选择、vLLM 评估命令的每个参数、评测的底层执行逻辑,以及单 GPU 与 TGI 两套历史方案的用法,帮助读者独立完成对任意 LLM4Decompile 系模型的客观评测。
评测体系概览:从“能反编译”到“可再执行”
LLM4Decompile 将反编译质量量化为一个非常务实的指标:可再执行率(Re-executability)。它的定义不是字符串层面的相似度,而是“反编译出来的 C 代码能否被 gcc 重新编译、并作为可执行文件运行且通过全部预设断言”。这一指标贯穿了主仓库 README 中列出的所有模型对比数据(1.3B~22B 各版本均以 Re-executability 百分比呈现)。
在评测物料上,项目按模型版本区分了两份测试集(详见 legacy-test 目录):
- V2 模型(LLM4Decompile-Ref 系列):应使用
decompile-eval-executable-gcc-ghidra.json。该测试集的input_asm_prompt是由 Ghidra 反编译出的伪代码(pseudo-code),例如下面这种带DAT_001020d0、param_1等典型 Ghidra 风格的中间表示:
undefined8 func0(float param_1,long param_2,int param_3) { int local_10; int local_c; local_10 = 0; do { local_c = local_10; if (param_3 <= local_10) { return 0; } while (local_c = local_c + 1, local_c < param_3) { if ((float)(DAT_001020d0 & (uint)(*(float *)(param_2 + (long)local_10 * 4) - *(float *)(param_2 + (long)local_c * 4))) < param_1) { return 1; } } local_10 = local_10 + 1; } while( true ); }- V1.5 模型(LLM4Decompile-End 系列):应使用
decompile-eval-executable-gcc-obj.json。该测试集的input_asm_prompt是由 objdump 反汇编得到的 x86-64 汇编指令,每条指令带有地址与二进制编码,例如:
<func0>: endbr64 push %rbp mov %rsp,%rbp mov %rdi,-0x18(%rbp) ...两份测试集都是 JSON 列表格式,每条样本包含五个字段:task_id(问题编号)、type(优化级别,取值 O0/O1/O2/O3)、c_func(HumanEval 问题的 C 参考实现)、c_test(C 断言测试)、input_asm_prompt(带提示词的汇编/伪代码输入)。每个问题对应 4 个优化级别条目,因此官方所称的“164 个函数”在评测数据中体现为 164×4 条样本。
推荐方案:基于 vLLM 的评估脚本
官方 README 明确标注 vLLM 方案为Recommended(推荐),原因是 vLLM 提供连续批处理(continuous batching)与张量并行,能在多 GPU 上以较高吞吐完成整批反编译生成。相关说明与更新记录见 evaluation/README.md,脚本主体为 evaluation/run_evaluation_llm4decompile_vllm.py。
安装依赖
pip install -r requirements.txt仓库根目录的 requirements.txt 中,vLLM 相关关键依赖包括vllm==0.4.0、numpy==1.23.3,同时评估脚本运行时还需要tqdm、loguru、transformers、multiprocessing等标准组件。若希望进一步加速接口侧的前缀计算,可额外安装 flash-attention 后端:
pip install flash-attn运行命令与参数逐项解析
在运行前,必须把--model_path改为本地模型路径(vLLM 从本地目录加载模型权重)。官方给出的完整命令如下:
cd evaluation # Before running the evaluation script, please update the model_path to your local model path. python run_evaluation_llm4decompile_vllm.py \ --model_path LLM4Binary/llm4decompile-6.7b-v1.5 \ --testset_path ../decompile-eval/decompile-eval-executable-gcc-obj.json \ --gpus 8 \ --max_total_tokens 8192 \ --max_new_tokens 512 \ --repeat 1 \ --num_workers 16 \ --gpu_memory_utilization 0.82 \ --temperature 0对照 run_evaluation_llm4decompile_vllm.py 中的parse_args(),各参数的默认值与作用如下:
| 参数 | 默认值 | 作用说明 |
|---|---|---|
--model_path | 必填(无默认) | 本地模型权重目录,脚本启动时会校验model_path.exists()且必须是目录,否则直接报Invalid model并返回 -1(见 脚本 L174-L178) |
--testset_path | 必填(无默认) | 测试集 JSON 路径,脚本用json.load加载并统计用例数 |
--gpus | 8 | 张量并行度(tensor_parallel_size),即用多少张 GPU 分摊一个模型 |
--max_num_seqs | 8 | 批处理中的最大序列数(源码中该参数被注释掉,实际未传入 vLLM) |
--gpu_memory_utilization | 0.82 | vLLM 可占用的单卡显存比例,显存紧张时应调低 |
--temperature | 0 | 采样温度;评测默认取 0(贪心解码),保证结果可复现 |
--max_total_tokens | 8192 | vLLM 的max_model_len,即输入+输出总长度上限;对应 v1.5 系列 4096 最大训练长度时留有余量 |
--max_new_tokens | 512 | 每个样本最多生成的新 token 数 |
--repeat | 1 | 整批生成重复轮数;>1时最终按多轮结果取平均,用于评估稳定性 |
--output_path | None | 若指定,把testset["output"]写入生成的解码结果后 dump 到该 JSON 文件 |
--num_workers | 16 | 评测阶段multiprocessing.Pool的进程数,控制 gcc 编译/运行检查的并发度 |
底层执行链路:vLLM 脚本是如何工作的
从源码结构看,run_evaluation_llm4decompile_vllm.py 的run_eval_pipeline()依次完成四件事:
- 校验模型与加载测试集:确认模型目录合法后读取 JSON,并用
AutoTokenizer.from_pretrained(model_path)加载分词器,stop_sequences = [tokenizer.eos_token]作为生成停止符。 - 构造提示词:脚本内部维护一个提示词前缀字典,对每条样本按其
type(O0~O3)拼接# This is the assembly code:\n+ 样本中的input_asm_prompt+\n# What is the source code?\n,构成送入模型的标准输入格式。 - vLLM 批量生成:以
LLM(model=args.model_path, tensor_parallel_size=args.gpus, max_model_len=args.max_total_tokens, gpu_memory_utilization=args.gpu_memory_utilization)初始化引擎,用SamplingParams(temperature=..., max_tokens=..., stop=stop_sequences)控制生成;repeat轮循环内把每轮输出整理为[[output.outputs[0].text] ...]收集到gen_results_repeat。 - 统计可再执行率:调用
decompile_pass_rate()用multiprocessing.Pool(args.num_workers)并行对每条反编译结果做编译+运行检查(详见下一节)。
指标计算的真正机制:编译检查与运行检查
这是整个评估体系最核心的部分,两个脚本的实现逻辑一致。evaluate_func()(见 vllm 脚本 L36-L106)对每条样本做如下处理:
- 抽取头文件:遍历
c_func与c_test中所有包含#include的行,集中到c_include,并从函数体与测试体中移除,避免声明与定义重复。 - 拼接两种产物:
c_combine = c_include + 反编译代码 + c_test(用于编译成可执行文件),c_onlyfunc = c_include + 反编译代码(用于生成汇编、验证语法)。 - 编译检查(flag_compile):先执行
gcc -S onlyfunc.c -o onlyfunc -lm验证反编译代码能否单独通过编译,再执行gcc combine.c -o combine -lm生成可执行文件;两次编译各有 10 秒超时,任何一次失败即返回(0, 0)。 - 运行检查(flag_run):以 10 秒超时执行生成的
combine可执行文件,捕获输出并要求check=True(即退出码为 0 才视为通过);若可执行文件因断言失败(assert不通过)或崩溃而返回非零退出码,则flag_run = 0。
随后decompile_pass_rate()按优化级别type分别累计compile、run与total,最终输出类似下面的结果,其中Run Rate 即可再执行率:
Optimization O0: Compile Rate: 0.xxxx, Run Rate: 0.xxxx Optimization O1: Compile Rate: 0.xxxx, Run Rate: 0.xxxx Optimization O2: Compile Rate: 0.xxxx, Run Rate: 0.xxxx Optimization O3: Compile Rate: 0.xxxx, Run Rate: 0.xxxx值得注意的是,repeat > 1时脚本会先按轮次分别统计,再对多轮结果取平均(源码中all_stats累加后除以len(gen_results_repeat)),因此它衡量的是“生成代码能够重新编译并跑通断言”的端到端能力,与 README 中强调的测试断言式验证(re-executability)完全对应。测试集字段c_func、c_test、input_asm_prompt的格式定义也可在 README.md 与 legacy-test 的样例数据中直接核对。
历史方案一:单 GPU、单进程评估脚本(legacy)
对于单卡、单进程的快速验证场景,官方保留了未随 vLLM 方案同步更新的旧脚本:
cd LLM4Decompile python ./evaluation/run_evaluation_llm4decompile_singleGPU.py该脚本(run_evaluation_llm4decompile_singleGPU.py)是理解整个指标机制的“最小实现”:
- 默认参数为
--model_path LLM4Binary/llm4decompile-6.7b-v1.5、--data_path ../decompile-eval/decompile-eval-executable-gcc-obj.json,也可通过命令行覆盖。 - 直接以
AutoModelForCausalLM.from_pretrained(..., torch_dtype=torch.bfloat16).cuda()加载模型,用model.generate(**inputs, max_new_tokens=512)逐条生成(不设 temperature,等价于贪心解码),并将tokenizer.pad_token = tokenizer.eos_token以对齐 padding。 - 提示词构造为
# This is the assembly code with {opt_state} optimization:\n+ 汇编 +\n# What is the source code?\n,其中opt_state取自样本的type字段。 - 指标统计同样复用“gcc 编译 + 执行”二元判定,最后把各优化级别的 compile rate 与 run rate 追加写入当前目录的
results.txt,格式为model:{...},opt:{...},compile rate:{...},run_rate:{...}。
由于该脚本使用shell=True方式调用 gcc、未设置编译超时(运行超时为 5 秒),且逐条串行生成,官方明确标注为 “legacy, not updated”,适合教学或单卡环境验证,大批量评测仍建议使用 vLLM 方案。
历史方案二:基于 TGI 的多进程评估(legacy)
官方 README 还记录了基于 Hugging Facetext-generation-inference(TGI)的评估方案,说明其特点是“10x faster, support multiple GPUs and multi-process”(相对单 GPU 串行而言),但同样标注为 “legacy, not updated”:
git clone https://github.com/albertan017/LLM4Decompile.git cd LLM4Decompile pip install -r requirements.txt # Before running the evaluation script, please update the model_path to your local model path. bash ./scripts/run_evaluation_llm4decompile.sh其中 TGI 的安装需按官方项目指引单独完成。整个 TGI 链路由三部分组成:
- scripts/run_evaluation_llm4decompile.sh:入口脚本,通过
workspace="$(pwd)"定位仓库根目录,再调用 Python 评估脚本,并传入--model_path llm4decompile-1.3b --max_new_tokens 512 --testset_path $workspace/decompile-eval/decompile-eval.json --repeat 1 --dtype bfloat16 --port 8080 --max_input_len 8000 --max_total_tokens 8512 --max_batch_prefill_tokens 36000 --num_shards 4 --num_workers 8。注意该脚本中测试集路径指向decompile-eval/decompile-eval.json,是较早版本的测试集命名,若当前仓库使用需按实际情况替换为 legacy-test/decompile-eval-executable-gcc-obj.json 或 Ghidra 版本。 - evaluation/run_evaluation_llm4decompile.py:评估主脚本。与 vLLM 版本几乎同构(同样包含
evaluate_func的编译/运行检查与decompile_pass_rate的统计),差异仅在推理后端:它通过 evaluation/server/text_generation.py 拉起 TGI 服务端并建立客户端。 - evaluation/server/text_generation.py:封装
TextGenerationServer与TextGenerationClient。服务端以text-generation-launcher拉起模型,参数包括--model-id、--port、随机生成的--master-port、--num-shard、--dtype、--max-input-length、--max-total-tokens、--max-batch-prefill-tokens,并轮询 127.0.0.1:8080 端口等待服务就绪;客户端基于AsyncClient异步并发请求,generate_code_results()以 50 个请求为一组(task_size=50)做asyncio.gather并发收集,num_outputs > 1时开启采样(do_sample=True,默认 temperature 0.8、top_p 0.95),否则贪心解码,并在返回前剔除stop_sequences中的停止符。
对应 run_evaluation_llm4decompile.py 的参数还包括--dtype(默认 bfloat16)、--port(默认 8080)、--max_input_len(默认 8192)、--max_total_tokens(默认 8800)、--max_batch_prefill_tokens(默认 72000)、--num_shards(默认 4),供调整服务端显存与吞吐。
测试集格式与样例解读
两份核心测试集均为 4594 行规模的 JSON 数组,每 4 条样本(O0~O3)对应同一个 HumanEval 函数。以decompile-eval-executable-gcc-obj.json的task_id: 0(判断数组中是否存在任意一对元素之差小于阈值的func0)为例:
c_func给出参考 C 实现(含#include <stdio.h>、<stdlib.h>、<math.h>);c_test给出main()内的多组assert断言(如assert(func0(a, 6, 0.3) == 1)等),评估时将其拼接到反编译代码之后;input_asm_prompt为objdump -d输出的<func0>:函数体汇编,包含endbr64、push %rbp、mov %rdi,-0x18(%rbp)等指令,以及被 README 预处理脚本清洗掉的地址/二进制列。
Ghidra 版本(decompile-eval-executable-gcc-ghidra.json)对应样本则直接给出 Ghidra 反编译伪代码作为模型输入。因此,选错测试集(例如用 V2 模型评测 obj 测试集)会因输入分布不匹配而无法反映模型真实能力,务必遵循 README 的版本对应关系。
评估前置条件与环境要求
- 评测输入是 x86-64 Linux 上的 GCC 产物,
evaluate_func依赖本机gcc(含-S与-lm链接数学库)以及能够执行编译产物,因此评估环境应为 Linux 并安装 gcc 工具链;这一点从两个评估脚本对subprocess调用 gcc 的硬编码可直接印证。 - vLLM 方案要求 GPU 环境满足显存与 CUDA 要求,
--gpu_memory_utilization需按实际显存调低,避免 OOM;--gpus张量并行度应不超过可用 GPU 数量。 - 测试集路径请以当前仓库实际位置为准:仓库中评测数据位于 legacy-test 目录(README 中引用的
../decompile-eval/...路径对应其历史布局),运行 vLLM 命令时需将--testset_path指向实际文件,例如../legacy-test/decompile-eval-executable-gcc-obj.json。 - 模型路径必须为本地目录(vLLM 方案中
model_path.exists() and model_path.is_dir()校验不通过会直接终止),运行前请把LLM4Binary/llm4decompile-6.7b-v1.5等占位符替换为已下载的 Hugging Face 模型本地路径。
小结:三条评估路径如何选择
| 方案 | 推荐度 | 并发/吞吐 | 适用场景 |
|---|---|---|---|
vLLM(run_evaluation_llm4decompile_vllm.py) | 官方推荐 | 张量并行 + 连续批处理 +num_workers进程池 | 多卡环境下的正式评测、复现模型对比 |
TGI(run_evaluation_llm4decompile.py+ scripts/run_evaluation_llm4decompile.sh) | legacy | 异步并发 +num_shards多分片 | 已部署 TGI 或需要自定义推理服务的场景 |
单 GPU(run_evaluation_llm4decompile_singleGPU.py) | legacy | 单进程串行 | 教学、快速验证、单卡小规模实验 |
无论选择哪条路径,其核心判定逻辑完全一致:把反编译代码与c_test断言拼接,gcc 编译、运行、断言全通过才算“可再执行”。理解这一点后,即使更换测试集或模型,也能准确解释评估脚本输出的 Compile Rate 与 Run Rate,并据此判断模型的真实反编译质量。
- 人工智能
- 大模型
- 逆向工程
- 微调
- 代码模型
【免费下载链接】LLM4Decompile
Reverse Engineering: Decompiling Binary Code with Large Language Models
相关推荐
LLM4Decompile终极微调指南:从零构建63.6%可执行率的反编译模型
LLM4Decompile终极微调指南:从零构建63.6%可执行率的反编译模型 LLM4Decompile是一款面向软件逆向工程领域的革命性工具,它利用大型语言
人工智能大模型逆向工程微调代码模型dex2jar与反编译质量评估:代码还原度指标
dex2jar与反编译质量评估:代码还原度指标 引言:反编译质量评估的重要性 在Android应用开发与逆向工程领域,.dex文件与Java字节码之间的转换是一
逆向工程开发工具Recommenders模型评估指南:10种评估指标全面解析与应用
Recommenders模型评估指南:10种评估指标全面解析与应用 Recommenders是一款专注于推荐系统最佳实践的开源项目,提供了全面的模型评估工具,帮
人工智能机器学习深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考