计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
re-binaryninja【效率与协作】Binary Ninja 工作流:MLIL、脚本 API。触发词:Binary Ninja、binaryninja、bn、MLIL
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
RE_DECOMPILER=binaryninja 场景下作为反编译器RE_DECOMPILER 会话变量,[[re-ghidra]] 默认)参考 [[re-analyze/platform-tips]]——Binary Ninja 静态分析免沙箱;脚本触发动态执行时默认沙箱内。
brew install --cask binary-ninja(社区 cask,需已有 license);Linux: 官网 tar 包解压运行 ./binaryninjaFunctions 面板有函数列表;Options > About 显示 license 类型xvfb-run ./binaryninja 可临时跑);批量任务直接走 headless(商业版),headless 不需要显示器pluginmanager 仅保留 shim)、bundled Python 升至 3.13(首次覆盖 Linux)而外部 Python 最低仍 3.10——2.x → 3.x → 4.x → 6.x 主版本间有破坏性 API 变更,脚本依赖先查 core_version() 与发行说明(见 [[gotchas]])python install_api.py(把 API 注册进 Python 环境;PyPI 无 binaryninja 包,pip install binaryninja 会失败)python3 -c "import binaryninja; print(binaryninja.core_version())" 输出与软件版本一致的版本号binaryninja-headless 可执行文件——正路是 install_api.py 注册后直接写脚本 binaryninja.load()(见 [[commands]] 序列 2);headless license 走官方独立下载包(无 GUI,仅 headless license 可下载)导入与分析:
File > Open 选样本 → 自动分析(底部进度条)→ 左侧 Functions / Data / References 视图确认分析结果Imports 视图)有内容、字符串(Strings 视图)可见Options > Analysis 勾选/关闭 pass——首次导入大文件或带混淆样本时先看这里,默认全开会慢MLIL 阅读(IL 视图切换):
i 在反汇编/LLIL/MLIL/HLIL 间循环,或右下角 Options 菜单选 IL 级别rax = rax ^ 0xdeadbeef)、类型恢复、条件跳转语义化——比裸反汇编可读,重点函数先看 MLIL 再下结论cmp eax, 0x1337 / jne L1 / mov byte [rdi], 1 / jmp L2 / L1: mov byte [rdi], 0 / L2: ... → MLIL 直接呈现 if (rax == 0x1337) *(uint8_t*)rdi = 1; else *(uint8_t*)rdi = 0;——读逻辑不用逐条跟跳转View > IL > LLIL,低语言 IL,保留指令级细节)→ 反汇编(Space/汇编视图)逐层核对m 键在 Binary Ninja 里是「整数应用枚举显示」,不是 MLIL 切换——切 IL 用 i重命名 / 类型:
n(或右键 Rename)——函数、变量、全局数据均可y(如 void *、DWORD、int (*)(void *, size_t)),类型传播自动改善后续反编译质量Types 面板新建 Structure → 应用到变量/指针 → 字段名随类型传播进反编译视图o 设指针引用、a 设字符数组、d 循环整型宽度、* 建数组(见 [[commands]] 快捷键表)Python 脚本(自动化标注):
import binaryninja
bv = binaryninja.load("sample.bin")
bv.update_analysis_and_wait() # 无头模式:手动触发完整分析
for f in bv.functions:
if f.analysis_skip_reason is None and f.medium_level_il:
n = len(list(f.medium_level_il.instructions))
if n > 200:
print(f"big function: {f.name} @ {hex(f.start)} len={n}")
bv.get_function_at(0x401000).name = "check_license" 后 bv.save() 写回str(f.high_level_il) 直接拿 HLIL 伪代码字符串——批量导出函数逻辑的最快方式File > Manage Plugins 的职责并入其中);插件目录按平台:Windows %APPDATA%\Binary Ninja\plugins、Linux ~/.binaryninja/plugins、macOS ~/Library/Application Support/Binary Ninja/plugins(macOS 非 ~/.binaryninja,放错不会被加载)File > Python 面板试跑(能看到 print 输出与异常),稳定后再转插件或无头脚本——调试脚本比跑完看结果快得多binaryninja-headless CLI,正路是 install_api.py 注册后写脚本(binaryninja.load() + update_analysis_and_wait(),即上文代码结构);headless license 用官方独立下载包;个人版受限时用 GUI 内 File > Python 面板执行同样代码bv.log_info 痕迹字符串/引用定位链:
Strings 视图找提示串 → 双击进反汇编 → 右键 Show References(或 xrefs 面板)→ 跳到引用函数 → MLIL 阅读bv.get_strings() + f.get_callers() 脚本化(见 [[commands]] 序列 2)DFG 数据流图(单值流向追踪):
Show DFG——从该指令出发的变量/常量传播路径图x/右键 Show References 交叉验证调用边界;DFG 视图 Esc 退出返回原视图证据核对(收尾):重命名/类型/注释随 bv.save() 落盘存档;无头导出产物(函数清单/HLIL 文本)与 [[re-triage]] 初勘值对照;关键结论写 [[re-analyze/analysis-contract]]——标注要能还原成报告,别只留在项目里
交叉验证(多反编译器互证):同一函数用 [[re-ghidra]] / [[re-ida]](若有)反编译对比——MLIL 与 Ghidra 伪代码结构一致时结论可信度提升;差异大时回 LLIL/汇编核对,优先相信汇编层证据
对比选型(价格 / 插件生态):
RE_DECOMPILER=binaryninja)import binaryninja 报版本错/行为与文档不符;原因——pip 包与安装软件主版本不匹配(API 大版本间不兼容);对策——重跑安装目录 install_api.py 对齐版本,core_version() 与 About 版本比对binaryninja.headless 不存在;原因——headless 自动化是商业版能力,个人版裁剪;对策——个人版用 GUI 内 File > Python 面板跑脚本,或脚本里只做 load + update_analysis_and_wait 的替代路径Options > Analysis 关掉多余 pass(如只保留 dataflow 与 decompile 需要的最小集),或只对重点函数做分析(f.analysis_skip_override 思路)bv.write 改了字节,反编译输出还是旧的;原因——分析结果缓存未失效;对策——改完调用 bv.update_analysis_and_wait() 强制重分析,或重新加载.bndb 项目库保存全部标注,样本本身不变——分发标注时传 .bndb(注意版本兼容),别指望样本里带上标注;写回样本字节是另一回事(脚本里 bv.write + 保存按官方 patch 流程走)Strings 视图中文/宽字符串显示乱码或分裂;原因——数据变量宽度判定错误;对策——选中数据后右键设 2 字节宽(或脚本 bv.get_data_var_at 后改类型),再触发分析