☰
SK²Decompile 在 BringUpBench O2 优化级别上的反编译评估报告解读:368 个函数的替换、编译与可执行率全解析
2026/10/2 13:26:20 网站建设 项目流程
  • 人工智能
  • 大模型
  • 逆向工程
  • 微调
  • 代码模型

【免费下载链接】LLM4Decompile

Reverse Engineering: Decompiling Binary Code with Large Language Models

项目地址:https://gitcode.com/GitHub_Trending/ll/LLM4Decompile
点击查看免费下载

本篇技术指南围绕 SK²Decompile 在 BringUpBench 基准上 O2 优化级别(-O2)的评估报告展开,逐项解读报告中的总体统计、按基准(Benchmark)细分的三项指标(Replacement / Build / Exec),并结合 eval_infer_out.py 的源码实现说明这些数字是如何通过"函数替换—重新编译—运行测试"的闭环自动测量出来的。读完本文,你将能够读懂并复现这份报告,理解反编译模型在中等优化级别下的真实能力边界与失败模式。

报告定位:O2 级别在整体评估中的位置

本报告(O2_results.md)属于 SK²Decompile 在 BringUpBench 上四个优化级别(O0–O3)评估报告之一。BringUpBench 是包含90 个自包含 C 程序的基准套件,零外部库依赖,仅依赖内置libmin库和 4 个系统调用,因此非常适合在无头文件缺失、无库依赖干扰的条件下评估反编译质量。SK²Decompile 将所有程序在 O0–O3 四个级别上编译、反编译并执行验证,共产生505 个函数(其中经推理过滤后实际评估 1488 个函数),并与工业级规则反编译器 IDA Pro(Hex-Rays)进行了对比,详见 bringupbench README。

O2 是编译器默认开启的常见优化级别,内联、寄存器分配、常量折叠等变换会显著改变二进制形态,是检验反编译器鲁棒性的关键难度档位。下表汇总了四个级别与 IDA Pro 的对照(数据来自 bringupbench README):

Opt LevelFunctionsSK²Decompile CompilableSK²Decompile ExecutableIDA CompilableIDA Executable
O038250.26%49.48%——
O137940.90%39.05%——
O236837.77%34.24%——
O335931.75%29.53%——
Avg148842.3%27.0%23.6%21.7%

可以看出,随着优化级别升高(O0 → O3),可编译率与可执行率单调下降,这是符合预期的:优化越激进,原始源代码结构信息丢失越多。平均而言,SK²Decompile 在全部 1488 个函数上取得42.3% 的编译率与 27.0% 的可执行率,高于 IDA Pro 的 23.6% / 21.7%(平均行数据取自论文 Section A.6 的 Table 8,各优化级别的 IDA 基线在论文中未单独报告)。

O2 报告总体统计:一次 100% 替换的完整评估

O2 报告头部给出了本次评估的运行元信息与总体结果:

  • Timestamp:20251119-170633
  • Source JSONL:merged.O2.func_map.infer.jsonl
  • Target:host(原生 x86-64 Linux)
  • Total cases:368
  • Replacement success:368(100.00%)
  • Compilable:139(37.77%)
  • Executable:126(34.24%)

三个指标的含义(依据 bringupbench README 的 Metrics 表与 eval_infer_out.py 源码):

MetricDefinition
Replacement Rate反编译输出能够被定位并替换回原始源文件中的函数占比
Compilable Rate替换后修改过的源文件能够成功编译(make build)的函数占比
Executable Rate编译后的程序能够通过其测试套件(make test,输出与参考一致)的函数占比

值得强调的是"Replacement success: 368 (100.00%)"这一项:说明 SK²Decompile 的推理输出(pseudo.content-fix字段)对于全部 368 个案例都能被精确定位并替换到原源文件中。从源码看,这一步骤由replace_function_body()实现(eval_infer_out.py):它先对原文、参考函数与推理输出做换行符归一化(canonicalize),再尝试三种匹配形态(原始文本、去尾空白加换行、去首尾空白),一旦找到精确子串即完成替换——这要求推理输出的函数体在文本层面与源码中的原始函数严格对齐。

Benchmark Breakdown:90 个程序在 O2 下的逐项表现

报告主体是 90 个基准程序(Benchmark)在 O2 下的逐项统计表。下表完整继承自 O2_results.md:

BenchmarkCasesReplacement%Build%Exec%
ackermann2100.00%50.00%50.00%
aes10100.00%20.00%20.00%
anagram13100.00%46.15%46.15%
audio-codec3100.00%33.33%33.33%
avl-tree15100.00%20.00%20.00%
banner1100.00%0.00%0.00%
bit-kernels3100.00%66.67%66.67%
blake2b4100.00%0.00%0.00%
bloom-filter4100.00%50.00%50.00%
boyer-moore-search3100.00%0.00%0.00%
bubble-sort3100.00%100.00%100.00%
c-interp10100.00%50.00%50.00%
ccmac1100.00%0.00%0.00%
checkers16100.00%68.75%62.50%
cipher3100.00%66.67%0.00%
congrad1100.00%0.00%0.00%
connect4-minimax13100.00%61.54%53.85%
convex-hull4100.00%75.00%75.00%
dhrystone5100.00%20.00%20.00%
distinctness2100.00%0.00%0.00%
fft-int4100.00%50.00%50.00%
flood-fill2100.00%50.00%50.00%
frac-calc10100.00%50.00%50.00%
fuzzy-match3100.00%33.33%33.33%
fy-shuffle3100.00%33.33%33.33%
gcd-list2100.00%50.00%0.00%
grad-descent4100.00%25.00%25.00%
graph-tests20100.00%10.00%10.00%
hanoi1100.00%0.00%0.00%
heapsort2100.00%50.00%50.00%
heat-calc1100.00%0.00%0.00%
huff-encode13100.00%92.31%92.31%
idct-alg3100.00%66.67%33.33%
indirect-test2100.00%50.00%50.00%
k-means6100.00%33.33%33.33%
kadane2100.00%50.00%50.00%
kepler7100.00%14.29%14.29%
knapsack3100.00%33.33%33.33%
knights-tour3100.00%33.33%33.33%
life14100.00%21.43%14.29%
longdiv6100.00%50.00%50.00%
lu-decomp3100.00%33.33%33.33%
lz-compress2100.00%100.00%100.00%
mandelbrot1100.00%0.00%0.00%
matmult1100.00%0.00%0.00%
max-subseq2100.00%0.00%0.00%
mersenne3100.00%0.00%0.00%
minspan8100.00%25.00%25.00%
monte-carlo1100.00%0.00%0.00%
murmur-hash2100.00%0.00%0.00%
n-queens3100.00%66.67%66.67%
natlog1100.00%0.00%0.00%
nbody-sim1100.00%0.00%0.00%
nr-solver1100.00%100.00%100.00%
packet-filter4100.00%0.00%0.00%
parrondo2100.00%50.00%50.00%
pascal3100.00%66.67%66.67%
pi-calc1100.00%0.00%0.00%
primal-test3100.00%33.33%33.33%
priority-queue5100.00%80.00%80.00%
qsort-demo7100.00%28.57%28.57%
qsort-test5100.00%80.00%80.00%
quaternions4100.00%0.00%0.00%
rabinkarp-search2100.00%0.00%0.00%
rand-test3100.00%0.00%0.00%
ransac2100.00%50.00%0.00%
regex-parser7100.00%28.57%14.29%
rho-factor3100.00%66.67%66.67%
rle-compress2100.00%0.00%0.00%
rsa-cipher4100.00%0.00%0.00%
sat-solver5100.00%60.00%60.00%
shortest-path3100.00%66.67%66.67%
sieve1100.00%0.00%0.00%
simple-grep1100.00%0.00%0.00%
spelt2num1100.00%0.00%0.00%
spirograph2100.00%50.00%0.00%
sudoku-solver4100.00%50.00%50.00%
tetris-sim12100.00%75.00%58.33%
tiny-NN4100.00%25.00%25.00%
topo-sort7100.00%0.00%0.00%
totient2100.00%50.00%50.00%
transcend1100.00%0.00%0.00%
uniquify1100.00%0.00%0.00%
vectors-3d8100.00%12.50%0.00%
verlet1100.00%0.00%0.00%
weekday2100.00%0.00%0.00%

从表格中可提炼的规律

高表现区间(≥80% Build/Exec):bubble-sort、lz-compress、nr-solver(均 100%),huff-encode(92.31%)、priority-queue与qsort-test(均 80%)。这些程序要么结构规整、要么逻辑简单直接,说明在 O2 下简单算法的函数级反编译恢复率很高。

中等区间(50%–80%):checkers(68.75% / 62.50%)、connect4-minimax(61.54% / 53.85%)、sat-solver(60.00%)、tetris-sim(75.00% / 58.33%)、sudoku-solver(50.00%)等。值得注意的是checkers、tetris-sim这类"规则密集型"程序,其 Build% 高于 Exec%,说明反编译结果语法正确但语义仍有偏差(函数能编译,但行为与测试期望不符)。

"编译成功但执行失败"的典型:cipher(Build 66.67% / Exec 0.00%)、gcd-list(50.00% / 0.00%)、ransac(50.00% / 0.00%)、spirograph(50.00% / 0.00%)、vectors-3d(12.50% / 0.00%)、regex-parser(28.57% / 14.29%)、idct-alg(66.67% / 33.33%)、life(21.43% / 14.29%)。这种"编译通过但运行结果错误"的模式在反编译评估中非常典型:类型、指针运算、边界条件等细微语义错误的函数依然能通过语法编译,但运行时行为与参考程序不一致。

完全失败(0.00%):banner、blake2b、boyer-moore-search、ccmac、congrad、distinctness、hanoi、heat-calc、mandelbrot、matmult、max-subseq、mersenne、monte-carlo、murmur-hash、natlog、nbody-sim、packet-filter、pi-calc、quaternions、rabinkarp-search、rand-test、rle-compress、rsa-cipher、sieve、simple-grep、spelt2num、topo-sort、transcend、uniquify、verlet、weekday等。这些程序在 O2 下没有任何一个函数能成功编译,往往是整体性的结构问题(例如topo-sort7 个函数全部失败,说明图数据结构的指针操作在 O2 优化后极难恢复)。

失败明细:Compilation Failures 与 Execution Failures 的判读

报告末尾以源文件::函数名@函数地址格式列出了两类失败。函数地址(如@0x1100、@0x18c0)对应二进制中的虚拟地址,可用于与 merged.O2.func_map.jsonl 中的pseudo.address字段精确对应。

Compilation Failures(229 条,略举代表性条目)

  • ackermann/ackermann.c::main@0x1100
  • aes/aes.c::aes_decrypt@0x18c0、aes/aes.c::aes_encrypt@0x1780、aes/aes.c::inv_mix_columns@0x1640、aes/aes.c::key_expansion@0x16d0、aes/aes.c::mix_columns@0x1580、aes/aes.c::shift_rows@0x1480、aes/aes.c::inv_shift_rows@0x14f0、aes/aes.c::main@0x1100
  • avl-tree/avlcore.c::Insert@0x1f30、avl-tree/avlcore.c::DeleteByElement@0x2860、avl-tree/avlcore.c::DeleteByElementRecursive@0x26d0、avl-tree/avlcore.c::DeleteLeftMost@0x2610、avl-tree/avlcore.c::DoubleLeftRotation@0x1c00、avl-tree/avlcore.c::DoubleRightRotation@0x1bd0、avl-tree/avlcore.c::FindByElement@0x1b00、avl-tree/avlcore.c::MakeEmpty@0x1f80、avl-tree/avlcore.c::CheckTreeNodeRotation@0x1c30
  • c-interp/c-interp.c::eval@0x3e90、c-interp/c-interp.c::function_body@0x37f0、c-interp/c-interp.c::function_declaration@0x3a10、c-interp/c-interp.c::next@0x1580
  • connect4-minimax/connect4-minimax.c::minimax@0x1840、connect4-minimax/connect4-minimax.c::play_game@0x1c90、connect4-minimax/connect4-minimax.c::score_position@0x1620、connect4-minimax/connect4-minimax.c::init_board@0x1230
  • graph-tests/graph-tests.c::main@0x1120、graph-tests/graph-tests.c::bfs@0x1540、graph-tests/graph-tests.c::depthFirstSearch@0x1b20等 20 个案例
  • life/life.c::main@0x1100、life/life.c::process@0x1550、life/life.c::getNumNeigbors@0x1390等 14 个案例
  • regex-parser/regex-parser.c::matchpattern@0x2670等 7 个案例

编译失败占比约 62%(229/368),是 O2 级别的"主要瓶颈"。从失败清单的分布可以推断:指针密集、结构体嵌套深、递归/回溯算法(avl-tree、graph-tests、c-interp、regex-parser)在 O2 优化后反编译结果的类型与语法恢复难度显著上升。

Execution Failures(13 条,完整列出)

  • checkers/functions.c::all_possible_moves@0x1a60
  • cipher/cipher.c::decipher@0x1360
  • cipher/cipher.c::encipher@0x12f0
  • connect4-minimax/connect4-minimax.c::terminal_score@0x1800
  • gcd-list/gcd-list.c::gcd@0x1310
  • idct-alg/idct-alg.c::idct_2d@0x12f0
  • life/life.c::init@0x1220
  • ransac/ransac.c::ransac_line_fitting@0x1410
  • regex-parser/regex-parser.c::matchpattern@0x2670
  • spirograph/spirograph.c::test@0x1390
  • tetris-sim/tetris-sim.c::clear_lines@0x1480
  • tetris-sim/tetris-sim.c::simulate_board@0x17c0
  • vectors-3d/vectors-3d.c::get_angle@0x17d0

执行失败的含义是:该函数反编译结果成功替换并编译通过,但运行make test时输出与参考不一致。观察这些案例可以发现语义错误的集中模式:gcd(辗转相除的循环边界)、idct_2d(浮点/查表变换)、clear_lines/simulate_board(游戏状态更新逻辑)、get_angle(向量夹角计算)、matchpattern(正则匹配)。这类案例是反编译"最后一公里"问题——语法正确但语义漂移,也正是 verl/SK2DECOMPILE 中基于编译器反馈的强化学习(GRPO)奖励函数所针对优化的对象。

这些数字是如何测出来的:评估脚本源码解析

报告中的每个数字都由 eval_infer_out.py 自动生成,其处理逻辑清晰地解释了指标口径:

  1. 逐案例处理(process_case):从 JSONL 中读取每个案例,用replace_function_body()把源文件中的原始函数文本替换为反编译结果(pseudo.content-fix);
  2. 隔离工作区(prepare_workspace):为避免案例间相互污染,每个案例复制Makefile、common/、target/及对应基准目录到独立临时工作区(eval_infer_out.py),默认--jobs 96并行处理;
  3. 依次执行make TARGET=host clean→make TARGET=host build→make TARGET=host test,每步默认 20 秒超时(--command-timeout 20);build 通过记为 Compilable,build 且 test 均通过记为 Executable;
  4. 聚合汇总(compute_summary/write_summary):按基准目录分组统计 Replacement / Build / Exec 三项比率,并输出 Compilation Failures(build failed)与 Execution Failures(build 成功但 test 失败)清单,最终生成 JSON 与 Markdown 两类报告。

复现报告只需预置数据 + BringUpBench 源码仓库:

# 1. 克隆 Bringup-Bench(上游基准套件) git clone https://github.com/toddmaustin/bringup-bench.git # 2. 配置路径(BENCH_REPO_ROOT 指向 bringup-bench 根目录) cd sk2decompile/evaluation/bringupbench vim config.env # 设置 BENCH_REPO_ROOT=/path/to/bringup-bench # 3. 运行 O2 评估 python3 scripts/eval_infer_out.py data/infer_results/merged.O2.func_map.infer.jsonl \ --jobs 16 \ --command-timeout 20 # 4. 查看结果 cat reports/O2_results.md

常用参数(默认值来自 eval_infer_out.py 的参数解析):

参数默认值说明
--jobs N96并行处理案例数(ThreadPoolExecutor并发)
--command-timeout S20每条 make 命令的超时秒数,0 表示不设超时
--limit NNone只处理前 N 个案例(调试用)
--keep-workspacesFalse保留临时构建工作区(默认处理完删除)
--targethost传给 make 的 TARGET 变量(默认原生 x86-64 Linux)
--bench-rootconfig.envBringup-Bench 仓库根目录,优先级 CLI > 环境变量 > config.env

配置文件的优先级同样体现在 config.env:BENCH_REPO_ROOT、IDA_BIN(Step 2 用)、DEFAULT_TARGET=host,均可被同名环境变量或 CLI 参数覆盖。

从报告到流水线:O2 数据在整个评估体系中的位置

报告对应的推理数据文件 merged.O2.func_map.infer.jsonl(368 个案例)源自上游 merged.O2.func_map.jsonl(441 个函数)。两者数量差(441 → 368)源于推理阶段的过滤——例如超过 token 上限的函数会被剔除(见 bringupbench README 的 Notes)。

整个 BringUpBench 评估采用五步流水线:编译(O0–O3)→ IDA Pro 伪代码基线 → 函数级真值映射 → SK²Decompile 两阶段推理 → 替换/编译/执行验证。其中 SK²Decompile 的两阶段推理由 sk2decompile_inf.py 完成:Phase 1(Skeleton,sk2decompile-struct-6.7b)将规范化伪代码恢复为结构中间表示,Phase 2(Skin,sk2decompile-ident-6.7)再恢复可读标识符,最终输出写入 JSONL 的pseudo.content-fix字段供 Step 5 验证使用。

如需在 O2 数据上完整复现反编译推理步骤:

cd sk2decompile/evaluation/ python3 sk2decompile_inf.py \ --dataset_path bringupbench/data/func_maps/merged.O2.func_map.jsonl \ --model_path LLM4Binary/sk2decompile-struct-6.7b \ --recover_model_path LLM4Binary/sk2decompile-ident-6.7b

需要说明的适用前提:SK²Decompile 的训练面向 C 语言 Linux-x64 代码(IDA 伪代码输入),其他语言或架构上的效果可能衰减;BringUpBench 程序自包含、零外部依赖,这保证了评估不受缺失头文件或库函数的干扰(见 sk2decompile README)。

结论与阅读建议

O2 报告给出了 SK²Decompile 在中等优化级别下的清晰画像:100% 的替换成功率保证了评估覆盖完整性;37.77% 的编译率与 34.24% 的可执行率表明近六成函数仍无法通过编译验证,且编译失败远多于执行失败,说明 O2 下反编译的"结构级恢复"仍是主要挑战;而cipher、vectors-3d等"编译通过但执行失败"的案例则指向语义精度问题。

若要继续深入研究,建议按以下顺序阅读仓库中的关联材料:

  1. O0_results.md / O1_results.md / O3_results.md——对比不同优化级别下的能力衰减曲线;
  2. bringupbench README——完整五步复现流水线与数据格式(func_map.jsonl、func_map.infer.jsonl字段说明);
  3. eval_infer_out.py——评估脚本的完整实现;
  4. sk2decompile_inf.py——两阶段推理管线的实现与参数。
  • 人工智能
  • 大模型
  • 逆向工程
  • 微调
  • 代码模型

【免费下载链接】LLM4Decompile

Reverse Engineering: Decompiling Binary Code with Large Language Models

项目地址:https://gitcode.com/GitHub_Trending/ll/LLM4Decompile
点击查看免费下载

相关推荐

上一篇:SwiftHTTP进度监控教程:实时跟踪网络请求状态
下一篇:mlcourse.ai 学习环境搭建与 Jupyter Book 构建指南(Software & DevOps 前置准备)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询