Page 18 - 《软件学报》2026年第6期
P. 18

李玉璋 等: BinDec: 面向  RISC-V  的  LLM  与符号执行协同反编译方法                                 2337


                 设计了评估指标.
                    在反编译代码的准确性评估中, 核心目标是验证反编译生成的代码与原始源代码在功能上是否等价. 由于程
                 序输入空间通常是无限的, 一般采用抽象方法               (例如符号执行) 来验证功能等价性. 但在本文中, 符号执行技术已
                 被整合进整体框架中, 因此不适合再作为外部评估手段. 考虑到我们所采用的数据集本身提供了高质量的测试用
                 例集合   (每个样本包含     30  个测试用例), 本文通过评估反编译代码在集成单元测试上的表现来衡量其质量, 并据此
                 定义了一系列量化指标, 具体评估流程如下所述. 首先, 将反编译得到的函数级代码单独编译为对象模块, 该阶段
                 是否成功编译称为函数可编译性            (RCf). 若编译过程中无错误产生, 则认为该函数满足             RCf 要求. 接下来, 将单元
                 测试模板程序与此函数模块进行链接, 由于链接阶段仍可能出现错误                       (例如函数签名不一致或调用约定不匹配),
                 此时的可编译性称为程序可编译性             (RCp). 若链接成功, 则生成可执行的测试程序. 随后, 运行所生成的测试程序,
                 若程序能够正常执行且未发生运行时错误               (例如内存非法访问或异常崩溃), 则认为该程序具备可执行性                   (RE). 最
                 后, 在程序可执行的基础上, 统计其在所有测试输入上的输出正确率, 作为评估功能一致性的关键指标, 即测试通
                 过率  (IOAcc). 该通过率基于数据集中每个样本对应的            30  个测试用例计算, 具体定义为通过用例数占总用例数的
                 比例. 综上所述, 函数可编译性关注函数模块本身的编译可行性, 程序可编译性侧重于模块与测试框架的链接能
                 力, 可执行性反映程序运行时的稳定性, 而测试通过率则从输入输出行为角度评估功能正确性. 这                             4  个指标共同构
                 成对反编译结果准确性的多层次评估体系.
                    对于反编译代码的可读性, 其便于人类理解的目标是一个主观概念, 直接进行大规模人工评估成本高昂且难
                 以复现. 因此, 在研究中广泛采用文本相似度作为可读性的可量化代理指标, 其基本假设是: 由经验丰富的开发者
                 编写、来自真实项目的源代码           (即本文数据集中的参考源代码) 具有较高的可读性. 因此, 反编译代码与参考源代
                 码在文本上的相似性可以在一定程度上反映其是否遵循了常见的编码惯例                          (如变量命名、代码结构), 从而间接衡
                 量其可读性. 具体来说, 我们采用        BLEU [33] 与编辑相似度  (edit similarity, ES) [24] 作为评价指标. BLEU  通过比较模型
                 生成的文本与参考文本之间的           n-gram  重叠程度来量化序列层面的共性. ES         则通过   Levenshtein  编辑距离量化两
                 个序列间的差异, 操作次数越少则相似度越高. 文本相似度可用于衡量生成的反编译代码与原始源代码之间的表

                 面相似性, 从而间接反映其是否具备与原始代码相近的可读性水平.
                    关于评估指标的局限性我们将在实验效度威胁部分                  (第  5.2  节) 进行讨论.
                  3.5   实现细节
                    本文实验主要使用       Python 3.10  进行开发, 所有实验在一台运行      Ubuntu 22.04  操作系统的服务器上开展, 其硬
                 件配置为   64  核  CPU (Intel(R) Xeon(R) Gold 5218 CPU @ 2.30 GHz), 192 GB  内存.
                    为提取函数级汇编指令序列及相关函数信息, 我们基于                   Ghidra (版本  11.4) 提供的  Python API 开发了定制插
                 件, 以实现反汇编功能. 为提取函数级           IR  代码片段, 我们基于    LLVM (版本   13.0.1) 的  API 实现了一个模块插件
                 (llvm::ModulePass). 在验证代码语义一致性时, 使用       KLEE [34]  (版本  3.1) 作为符号执行引擎, 并搭配    Z3 (版本
                 4.9.1) 作为  SMT  求解器. 为在 x86-64 架构的测试机上运行     RISC-V  架构的可执行程序, 采用      QEMU-RISCV64 (版
                 本  6.2.0) 作为二进制模拟器. 为实现对      RISC-V  二进制程序中特定函数的注入, 使用           LUI 与  JALR  指令组合对待
                 替换函数所在内存位置进行指令覆盖, 从而将原始函数调用重定向至替换位置. 该指令组合支持                              32  位地址空间内
                 的绝对地址跳转, 我们在使用         QEMU-RISCV64  时将虚拟地址空间大小限制为          1 GiB, 以兼顾该指令组合的跳转空
                 间限制和人工分析的便利性. 在         LLM  方面, 直接调用公有云提供的大模型           API 服务, 使用的模型为     DeepSeek-V3.

                  4   实验结果与分析
                    为了评估本文所提出的         BinDec 方法的效果, 本节详细报告设计的实验问题, 并对实验结果进行分析.

                  4.1   问题  1: 与基线方法相比, BinDec 方法在  RISC-V  二进制代码的反编译任务上表现如何?
                    针对问题    1, 我们依据第    3  节所述的实验设置进行了验证. 在二进制代码提升与中间代码反编译两个阶段中,
   13   14   15   16   17   18   19   20   21   22   23