Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
VulnFanatic-NG — 用于在反编译的二进制文件中识别漏洞的BianryNinja插件,同时支持程序化扫描和LLM辅助。 | Kitploit
工具/GitHubGitHub/martyx00/vulnfanatic-ng
静态代码分析 (SAST)漏洞分析代码分析漏洞利用逆向工程模糊测试渗透测试硬件安全二进制分析供应链安全学习与教育AI 辅助逆向
14152个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
GitHub
martyx00/vulnfanatic-ng

VulnFanatic-NG

用于在反编译的二进制文件中识别漏洞的BianryNinja插件,同时支持程序化扫描和LLM辅助。

查看仓库

VulnFanatic-NG

LLM 辅助的漏洞研究,用于 Binary Ninja。

VulnFanatic-NG 添加了一个侧边栏面板,扫描当前二进制文件,并询问一个 LLM — 默认是本地托管的与 OpenAI 兼容的模型,或 Anthropic Claude、Google Gemini、或 Azure OpenAI(见 LLM backends)— 来判断可疑代码是否真的存在漏洞。它主要基于 Binary Ninja 的反编译器输出(HLIL),必要时回退到汇编代码,并且只报告已确认的问题,附带可点击的代码引用。


工作原理

扫描运行最多三个阶段(第三阶段是可选且仅在线):

第一阶段 — 危险函数调用

查找在 rules/phase1_rules.json 中定义的危险函数的调用点 — strcpy、memcpy、sprintf/格式字符串、system、alloca、scanf、命令/执行 API、弱随机数生成、free/delete 系列(释放后使用 / 双重释放)、将不可信输入读入固定缓冲区(recv/read/fread/ReadFile)、SQL 注入(sqlite3_exec/mysql_query/PQexec)、禁用的 TLS 证书验证(SSL_CTX_set_verify/curl)、SSRF,以及不正确的权限管理(setuid/setresgid)、memset/bzero 系列,还有与攻击者控制长度进行比较(memcmp/strncmp → 认证绕过),涵盖 C/C++、Win32 和(尽力而为的)Rust FFI。覆盖范围包括加固后的 _chk(FORTIFY)和 Annex-K _s 变体。有界格式化输出函数(snprintf 及其变体)有自己的默认安全规则,因此正确的 size 参数不会报告为溢出。调用点通过三种方式查找:直接调用命名符号;通过转发桩 / PLT 存根路由的调用(恢复真正的调用者,因此不会漏掉仅通过存根访问的导入);以及 — 除非 vulnfanatic.scanIndirectCalls 关闭 — 通过函数指针或虚表分派的间接调用,Binary Ninja 已将其解析为危险函数。对于每个调用点,它构建一个过程间、以反编译器为中心的上下文,预算到一个 token 限制(默认 100k):

  • 调用表达式及其参数,
  • 被调用函数的声明原型(来自 Binary Ninja 的类型信息,否则来自内置表),以便模型正确地将参数映射到形参 — 加固后的 __*_chk 和边界检查的 *_s 变体带有额外的前导参数,会改变格式/大小/目标的位置,
  • 每个调用参数的类型和字节大小(缓冲区容量),从参数的 HLIL 表达式类型派生,因此像 s->buf 这样的结构体字段解析为该字段的真实数组大小,而不是 s 的指针大小;类型部分中的 struct 定义也会携带每个字段的字节大小,
  • 每个参数的常量值 / 范围,由 Binary Ninja 的常量传播和值集分析解析(例如,长度经证明为常量 0x40 或范围限定为 [0, 0xff]),模型将其用作将大小与缓冲区容量进行比较时的真实依据,而不是猜测,
  • 调用函数的栈帧布局(变量偏移和字节大小),当它包含固定大小的缓冲区时,因此可以根据相邻变量和保存的返回地址判断栈溢出(vulnfanatic.includeStackLayout),
  • 路径约束(保护调用的 if/循环/switch 条件),
  • 参数数据流摘要 — 每个调用参数在函数内定义和使用的位置,
  • 跨调用者的参数解析 — 当危险参数是调用函数的参数时,上下文报告每个调用者实际传递的内容(例如“所有调用者传递一个字符串字面量”),因此始终为常量的格式/大小参数不会被误认为是攻击者可控的,
  • 调用函数的完整反编译体,
  • 数据类型定义(struct/union/enum),用于调用链和参数变量中引用的类型,因此模型知道真实的缓冲区/字段大小和整数宽度,
  • 产生或消耗调用参数变量的函数的反编译体(通过 HLIL 的 def/use 追踪),这是释放后使用 / 双重释放以及污染大小推理成为可能的原因,
  • 从入口点/导出函数向下到调用的调用路径,
  • 这些调用路径上每个函数的反编译体(最靠近危险调用优先),每个都注释有调用点和保护下一步的条件,

该上下文加上特定于规则的提示被发送给模型,模型返回一个结构化的判定。非问题被丢弃。提示针对强大的本地代码模型(例如 Qwen2.5-Coder)进行了调整,并指示其分析整个流程并仅输出 JSON。

推理、草稿框和置信度

模型被指示偏好召回 — 报告合理的、与安全相关的问题,并通过 置信度 表达不确定性,而不是丢弃任何无法完全证明的内容。它在一个草稿框中展示其工作,其中引用了它所依赖的逐字代码片段(输入的源代码、每个守卫、大小/长度、相关类型和接收点),该草稿框存储在发现项中,以便您可以审计推理。

每个发现项都带有置信度(高/中/低):高 = 整个链都在上下文中显示;中 = 可能,推断出一个或两个链接;低 = 值得手动审查的线索。这是主要指标(模型的严重性估计是次要字段)。设置 vulnfanatic.minConfidence 以丢弃低于阈值的任何内容。

调整精度与召回

默认情况下,VulnFanatic-NG 偏向召回(捕捉真实问题)。如果误报太多,请使用以下任一方式收紧:

  • vulnfanatic.validationPass(默认关闭)— 运行第二次 LLM 检查,对每个标记的问题针对相同上下文进行双重检查(验证草稿框片段并重新追踪流程),并可以纠正判定或置信度。对标记的候选者,LLM 调用次数翻倍。
    • 单独的验证模型(推荐在使用验证检查时使用)。 设置 vulnfanatic.validatorModel(加上 validatorProvider / validatorBaseUrl / validatorApiKey)以在不同模型上运行第二次检查。来自独立模型的第二意见要有用得多——它共享更少的盲点,并且不太可能盲目赞同第一个判定(模型往往偏好自己的答案)。一个好的模式是级联:一个快速模型作为分析器(广泛召回),您最强的模型作为验证器,只对标记的候选者运行。留空验证模型以使用分析器模型进行验证。验证器应至少与分析器一样有能力——较弱的验证器大多会增加误拒。除 provider/base URL/key/model 外,所有内容都从分析器连接设置继承;空白的验证器密钥重用分析器密钥;如果验证端点不可达,则保留第一个判定(发现项永远不会因验证器中断而丢失)。
  • vulnfanatic.minConfidence(默认 low)— 提升到 medium/high 以仅报告更强的发现。
  • vulnfanatic.skipConstantArgCalls(默认关闭)— 跳过参数全部为编译时常量的溢出类调用点。

速度。 大多数每次调用的延迟在于书面的推理,因此 vulnfanatic.verdictReasoning 控制模型写入多少:

  • concise(默认)— 简短的 1–3 句理由,无逐字代码。比 full 快得多且几乎没有精度损失;您还可以降低 vulnfanatic.maxResponseTokens。
  • full — 带有引用片段的详细草稿框(最可审计,最慢)。
  • none — 仅判定。最快;配合具有推理能力的后端(vulnfanatic.reasoningEffort),以便模型的内部思考完成工作。在普通的本地模型上,none 会失去精度(完全没有思维链)。

始终开启的精度支持功能(它们告知模型而不抑制发现):

  • 参数溯源 — 上下文告诉模型每个参数是编译时常量、函数参数还是源自污染源,模型据此设置置信度。
  • 边界检查变体感知 — 提示将 _s(Annex K)和 _chk(FORTIFY)变体以及长度限制的 API 视为安全,除非 size 参数本身错误。
  • 显式缓冲区大小 — 提供参数和结构体字段的字节容量,以便模型将容量与写入的字节进行比较,而不是猜测。

离线扫描(无 LLM)

离线扫描按钮运行第一阶段且无模型——完全基于 phase1_rules.json 中每个规则的 offline 块中声明的编程启发式。它标记危险的调用点并消除明显安全的那些,分配启发式的置信度:

  • 已消除(不报告):具有常量长度的 memcpy/memmove、来自常量字符串的 strcpy、具有常量格式的 printf、具有常量命令的 system 等——其控制参数是编译时常量因此不能是攻击者可控的调用。“常量”包括 Binary Ninja 的值集分析已将其固定为上游固定值的情况,而不仅仅是字面参数。
  • 高置信度:标记后未在执行流程中找到任何缓解检查。
  • 降级(→ 中):size/length 参数要么被 Binary Ninja 的值集分析解析为常量/有界范围,要么在流程中的某个位置找到了对相关参数的比较(例如,strlen/大小比较、if (len < …))——包括在路径上调用的函数中——因此可能已经被处理。(仅提及变量而不进行比较的分支不再计入,消除了虚假降级的一个来源。)

启发式使用规则中的一个小型声明性词汇表(constant_safe_args、eliminate_if_all_args_constant、format_arg_lookup、length_guard_vars、base_confidence、skip),由 Python 谓词评估——无需嵌入代码来 exec。大多数规则都有离线定义(溢出、格式字符串、命令执行、scanf、路径处理、弱随机数、弱数字解析、权限更改、分配大小等)。只有两个确实需要语义分析的类别在离线时被跳过,留给 LLM:free/delete 系列(释放后使用 / 双重释放,需要指针生命周期跟踪)和 TLS 验证(漏洞是一个特定的常量值,如 SSL_VERIFY_NONE)。离线摘要报告有多少站点被标记 / 消除 / 跳过(需要 LLM) / 失败,因此计数相加。这是一个快速分类;如需真实判断——以及针对跳过的类别——运行完整的 LLM 扫描。

离线发现仍然构建在线扫描会发送的相同完整的过程间上下文(仅针对标记的站点)并存储它,因此一旦您分类它们,它们可以像在线发现一样导出为微调数据。如果希望最大离线速度,请使用 vulnfanatic.offlineBuildContext 禁用。

第二阶段 — 安全敏感代码(符号门控)

仅在二进制文件看起来具有真实符号/变量名称时运行。定位在 rules/phase2_rules.json 中定义的安全敏感函数 — 认证、加密(包括弱算法)、签名/证书验证、会话/令牌处理、访问控制、秘密/密钥处理、输入验证、非常量时间秘密比较,以及不安全反序列化 — 通过函数名称和引用的字符串匹配,然后由模型审计。

第三阶段 — 硬件攻击加固审计(在线,可选)

一种固件加固审计,针对故障注入(电压/时钟/电磁故障注入)和侧信道(时序/功耗)攻击,基于硬件攻击缓解指南。与第一、二阶段(寻找漏洞)不同,第三阶段报告安全关键函数上的缺失或违反的加固控制 — 例如:默认失败分支、双重检查的安全决策、循环后的计数器验证、高汉明距离状态常量(相对于普通 0/1)、常量时间全长秘密比较、随机偏移的秘密访问/清除、先加密后验证(防 DFA)、控制流完整性计数器、避免用户态加密,以及不直接处理原始密钥材料(rules/phase3_rules.json)。

因为编译器优化可以剥离源代码级保护,这些控制最好在编译后的二进制文件上验证——正是此功能检查的内容。第三阶段是仅 LLM(在线)、符号门控,并且默认禁用;在新扫描选项卡上使用第三阶段复选框逐次启用(它从不以离线模式运行)。

发现项列在表格中(状态、置信度、阶段、CWE、函数、地址、标题),带有详细信息面板,显示解释、分析草稿框和验证注释。双击一行导航二进制视图到代码。

分类工作流

每个发现项从未分类开始。右键单击一行以设置其状态 — 标记为真实问题、标记为误报或标记为未分类。每次状态更改都会弹出一个**“提供原因:”文本框(原因与发现项一起存储)。表格使状态一目了然:真实问题为绿色/粗体并排序到顶部**,误报为灰色/删除线并排序到底部,未分类位于中间,带有其置信度颜色。摘要行显示计数。

每个结果选项卡都有一个导出已分类(微调)… 按钮,该按钮导出仅已分类的发现项(真实问题 + 误报)为 OpenAI 聊天格式 JSONL 以进行微调:每个示例将原始系统+用户提示与人工纠正的判定配对作为助手目标(误报教导 is_vulnerable=false 并带有您的原因;真实问题强化 is_vulnerable=true),因此您可以迭代改进模型在您的二进制文件上的准确性。

详细信息面板中显示的每个发现项的上下文(并用于重建微调提示)默认完整保留 — 由 vulnfanatic.storedContextChars 控制(0 = 无限制;设置一个正的上限,例如 4000,以限制 BNDB 增长,但代价是上下文保真度)。

多次扫描(选项卡)

面板是选项卡式的。第一个选项卡始终是新扫描,您可以在此设置:

  • 可选的扫描名称(空白 → <timestamp> <mode>,例如 2026-06-15 14:03:50 offline),
  • 可选的第一阶段 / 第二阶段 / 第三阶段自定义规则路径(空白 → 捆绑的默认值),因此您可以运行替代规则集,
  • 一个第三阶段复选框(默认关闭),以额外运行仅在线的硬件攻击加固审计,

然后按开始扫描或离线扫描。每次运行都会打开自己的结果选项卡,发现项实时流式传输到其中。所有扫描都存储在 BNDB 中,因此例如您可以保留离线扫描,稍后添加在线扫描,或并排比较使用不同规则集的运行 — 当您重新打开数据库时,它们会作为选项卡重新出现。关闭选项卡将永久从 BNDB 中删除该扫描 — 为防止意外,它会弹出一个确认框,需要勾选 “我确认我将永远失去来自 的结果。” 后才能激活 永久删除结果 按钮。导出当前扫描… 将选中的选项卡写入 Markdown/JSON。

每个打开的二进制文件都有其自己的独立面板状态 — 自己的扫描选项卡和正在运行的扫描。在一个二进制文件中启动扫描并切换到另一个二进制文件会显示第二个二进制文件的结果(并允许您单独扫描它);第一个二进制文件的扫描在后台继续运行,并在切换回来时保持不变。


安装

此插件的包文件夹名为 vulnfanatic_ng(一个有效的 Python 标识符 — Binary Ninja 将插件文件夹名称作为模块导入,因此像 VulnFanatic-NG 这样的连字符名称将无法加载)。

  1. (可选) 将准确的 token 计数安装到 Binary Ninja 的 Python 中: ``` pip install tiktoken

    root@kitploit:~
  2. 符号链接或复制 vulnfanatic_ng 文件夹到你的 Binary Ninja 用户插件 目录:

    • macOS: ~/Library/Application Support/Binary Ninja/plugins/
    • Linux: ~/.binaryninja/plugins/
    • Windows: %APPDATA%\Binary Ninja\plugins\

    例如,在 macOS 上: ``` ln -s "$(pwd)/vulnfanatic_ng" "$HOME/Library/Application Support/Binary Ninja/plugins/vulnfanatic_ng"

    root@kitploit:~
  3. 重启 Binary Ninja(或运行 重新加载插件)。右侧边栏会出现一个 VF 图标。


配置

打开 设置(齿轮图标 / 编辑 ▸ 首选项 ▸ 设置)并搜索 vulnfanatic。至少设置以下项:

LLM 后端

vulnfanatic.apiProvider 选择请求的构造和认证方式。判决协定(以及所有规则提示)在所有提供者中相同。

AWS Bedrock 可以通过 openai 提供者的 OpenAI 兼容端点使用,因此不需要专用后端。

其他实用设置:vulnfanatic.maxContextTokens(默认值 100000)、vulnfanatic.maxResponseTokens、vulnfanatic.temperature、vulnfanatic.reasoningEffort(off/low/medium/high;默认 high — 在支持的情况下要求模型在回答前进行思考,按提供者映射:openai/azure 使用 reasoning_effort,anthropic 使用自适应思考 + output_config.effort,google 使用动态 thinkingConfig;如果模型拒绝则自动移除并重试)、vulnfanatic.requestTimeoutSec、vulnfanatic.callPathMaxDepth / vulnfanatic.callPathMaxPaths、(包含调用路径上函数的反编译体;默认开启)/ (上限,默认 12)、(同时包含路径上调用的其他函数,这些函数可能包含边界/验证检查;默认开启)/ (上限,默认 12)、(包含结构体/联合体/枚举定义;默认开启)/ (上限,默认 24)、(追溯调用参数的生成者/使用者并包含这些函数体;默认开启)/ (上限,默认 8)、(当调用函数具有固定大小缓冲区时包含其栈变量布局;默认开启)、(同时匹配通过已解析的函数指针/vtable 分发的危险调用;默认开启 — 对于非常大的二进制文件可关闭以加快扫描速度)、(运行第二次双重检查流程;默认关闭)/ / / / (在独立模型上运行验证流程 — 空白 = 与分析者使用相同模型)/ (//;丢弃低于此置信度的发现;默认 )、(将模型无法评分的站点报告为 置信度的“未评分”线索,而不是丢弃它们;默认开启)、(跳过所有常数值溢出的调用点;默认关闭)、(//;模型每个判决写入多少推理 — 主要速度杠杆;默认 )、 / / (启用每个阶段;阶段 3 仅在线,通常通过扫描界面的复选框而非此处切换)、 / 、(用于估计 token 数的 tiktoken 编码;如果未安装 tiktoken 则回退到字符启发式)、(为离线发现构建完整上下文以便导出进行微调;默认开启)、(向控制台输出详细的管道跟踪信息;默认关闭)/ (编辑所有识别二进制文件的细节,使日志可以共享 — 参见下方的)、、(验证 HTTPS 证书;默认开启)/ (HTTPS 的 CA 证书包 — 如果遇到 请参见故障排除),以及 / / (将这些指向您自己的规则文件以自定义检测和提示)。

安全说明: API 密钥以明文形式存储在 Binary Ninja 的设置中。对于敏感密钥,请优先使用环境变量覆盖。

测试模式(试运行,无 LLM)

将 vulnfanatic.apiBaseUrl 设置为字面值 TEST 以在无任何 LLM 的情况下运行:

  • 模型永远不会被调用(无需网络,无需 API 密钥/模型)。
  • 每个候选(阶段 1 中的每个危险调用点,阶段 2 中的每个安全敏感函数)都会被标记。
  • 每个候选的完整提示 — 系统提示和完整生成的上下文 — 都会写入 /tmp/vulnfanatic_ng/<binary>-<timestamp>/ 下的单独文件中。
  • 发现表格显示一个提示文件列(悬停显示完整路径),详细信息窗格和导出都包含该路径。

使用此功能检查和验证 VulnFanatic-NG 将要发送给模型的内容,并在不花费模型时间的情况下迭代规则提示/上下文。

调试日志

启用 vulnfanatic.debugLogging 可将扫描管线的详细逐步跟踪信息(在线和离线)打印到 Binary Ninja 日志/控制台:每个调用点、每次跳过/清除决策、上下文构建(仅大小)、每次 LLM 请求(提供者/模型/端点、重试、回退)、每个判决以及每个报告发现。API 密钥不会被记录。

当调试日志开启时,在线扫描会在结果表中保留每个候选,而不是丢弃那些未成为确认问题的候选,每个候选都标记有仅调试状态(暗显,排序在底部):

  • REJECTED — LLM 返回的判决为不是问题。
  • SKIPPED — 在 LLM 之前被可证明安全的规则消除(常量格式字符串或全常量参数);该行会解释是哪一条。
  • ERROR — 候选无法分析(上下文构建失败,或 LLM 响应无法解析 / 连接失败);该行带有错误信息。

因此,调试扫描会在 /N 总数中为每个候选显示一行,并且摘要会分别报告问题与已拒绝/已跳过/错误的数量。您可以右键单击这些行中的任何一行,将其重新分类为真正问题或误报(这使其有资格进行微调导出)。(离线扫描不受影响 — 它们从不调用 LLM。)

独立于调试模式,当模型返回无法解析的响应时 — 例如 Gemma 的 <unused…> 这样的无关 token、散文而非 JSON,或空消息(仅包含 role,无 content) — 客户端会执行一次纠正性重试,重新仅请求 JSON,同时禁用结构化输出格式;如果成功,则扫描剩余部分保持格式关闭。客户端还会在 content 为空时读取推理通道(reasoning_content / reasoning),因此将答案放在那里的推理模型仍然有效。

空消息情况常见于通过 OpenAI 兼容 API(例如 mlx-community/gpt-oss-20b)提供的诸如 GPT-OSS / o1 之类的推理模型:当设置了 response_format=json_object 时,和谐的“最终”答案通道通常会被抑制,服务器返回无内容的 {"role": "assistant"}。这些模型还可能将整个输出预算消耗在推理通道上,并在思考过程中被截断,返回无任何 JSON 的散文。自动重试可恢复与格式相关的情况;如果仍然持续,请关闭 vulnfanatic.sendJsonResponseFormat、降低 vulnfanatic.reasoningEffort(以便减少思考预算),和/或提高 vulnfanatic.maxResponseTokens。持续的 <unused…>/垃圾回复通常意味着提示超出了模型的上下文窗口(设置 vulnfanatic.modelContextWindow 和/或提高服务器的上下文长度),或者模型不适合严格的 JSON 输出(代码模型如 Qwen2.5-Coder 在此处表现远好于 Gemma)。

召回保留回退。 如果重试后仍无法为候选评分,vulnfanatic.flagUnparseableResponses(默认开启)仍会将其报告为**“未评分”**的发现,置信度为 UNKNOWN — 这是一个与 low 不同的值(模型从未产生判决,因此不是低置信度的判断),会排序到底部 — 保留模型的部分输出作为解释,这样您不会丢失该站点,只需手动审查。关闭它以丢弃此类站点(它们只会作为分析错误或调试错误行出现)。

同时启用 vulnfanatic.debugAnonymous 可使日志安全共享:它会删除所有可能识别分析文件的内容 — 符号/变量名称和地址变为每次运行的加盐哈希(仍在一次运行内一致,因此可追踪流程),文件名被隐藏,发现文本替换为 <redacted>,LLM 端点主机被哈希,反编译代码/提示/上下文仅记录大小(从不记录内容)。因此您可以发送调试日志报告问题,而不会泄露有关二进制文件的任何信息。


使用

  1. 打开一个二进制文件并让分析完成。
  2. 单击侧边栏中的 VF 图标以打开 VulnFanatic-NG。
  3. 按 开始扫描(完整 LLM 扫描)或 离线扫描(快速的、无需 LLM 的编程阶段 1 — 见上)。进度显示在面板和 Binary Ninja 状态栏中;发现实时出现,并且可以取消。
  4. 单击发现以阅读解释;双击跳转到代码。
  5. 右键单击发现以标记为误报 — 它会移动到表格底部,变灰并划掉,菜单项切换为标记为真正问题以撤销。(右键菜单还有转到代码。)
  6. 导出为 Markdown 或 JSON,或清除以丢弃已保存的发现。

发现 — 包括其误报状态 — 存储在 Binary Ninja 数据库中。当您保存数据库时,它们会写入 .bndb(如果 .bndb 已存在则立即刷新),因此会在重新打开时保留。

扫描会分析每个匹配的调用点(无上限),这适用于本地模型。对于托管/付费端点,请注意大型二进制文件的数量。


自定义规则

两个规则文件共享一个封装结构,包含一个公共的 system_prompt 和 output_schema,以及一个 rules 列表。复制捆绑的文件,编辑函数/关键字/提示,并将 vulnfanatic.rulesPhase1Path / vulnfanatic.rulesPhase2Path 指向您的副本。阶段 1 规则通过 functions(精确匹配)和 name_regex 匹配;阶段 2 规则通过 name_keywords、name_regex 和 string_keywords 匹配。每个规则的 prompt 可以使用 {function} 占位符。


微调模型(MLX,Apple Silicon)

经过分类的导出文件被设计为可直接反馈给模型。在多个二进制文件中对发现进行分类后,在每个文件上单击导出分类结果(微调)…(将 .jsonl 文件收集到一个文件夹中),scripts/finetune_mlx.py 会在这些文件上运行 MLX LoRA 微调。```bash pip install mlx-lm # Apple Silicon / macOS

Fine-tune a local 4-bit model on every *.jsonl under ./exports

python scripts/finetune_mlx.py ./exports
--model mlx-community/Qwen2.5-Coder-7B-Instruct-4bit
--adapter-path ./vf-adapters --iters 800

...then fuse the adapters into a standalone model

python scripts/finetune_mlx.py ./exports --model
--fuse --fused-path ./vf-qwen-coder-vuln

root@kitploit:~
该脚本将 **训练数据文件夹** 作为位置参数,以及基础 **`--model`**(本地路径或 MLX/HF 仓库 ID);其他参数为可选:`--adapter-path`、`--valid-split`(0.1)、`--iters`、`--batch-size`(自动钳制以适应小分割)、`--num-layers`、`--learning-rate`、`--max-seq-length`(`0` = **自动适配** 最长示例,上限为 16384;设置为正值可强制指定)、`--fine-tune-type`(`lora`/`dora`/`full`)、`--seed`、`--fuse`/`--fused-path`,以及 `--dry-run`(准备数据并打印命令,不进行训练)。`--` 之后的所有内容将原样传递给 `mlx_lm lora`。它会递归合并文件夹中所有 `*.jsonl` 文件,验证并 **去重** 聊天示例,生成 MLX 所需的 `train.jsonl`/`valid.jsonl` 分割,然后启动 `python -m mlx_lm lora`(如果使用 `--fuse`,还会执行 `mlx_lm fuse`)。

使用兼容 OpenAI 的服务器(`mlx_lm.server --model <path>`)提供结果,并将 `vulnfanatic.apiBaseUrl` 指向它,以便使用您调整后的模型进行扫描。

> VulnFanatic-NG 上下文很大,因此默认情况下脚本会 **自动适配** `--max-seq-length` 到最长的示例(向上取整,上限为 **16384 个 tokens**)。长序列会主导训练内存,因此接近此上限的大型模型可能导致较小的 Mac 内存不足。如果示例超过上限,它们会被截断——在导出前传入更高的 `--max-seq-length`(更多内存)或降低 `vulnfanatic.storedContextChars`。如果训练因信号终止(例如 `exit -10` / SIGBUS),则属于内存不足崩溃:降低 `--max-seq-length`,添加 `-- --grad-checkpoint`,或使用更小的模型。

---

## 开发与测试

该插件没有必须的第三方依赖。纯模块(`rules`、`tokens`、`llm`、`findings`、`settings`、`prototypes`)由一个离线测试套件覆盖,该套件既不需要 Binary Ninja,也不需要网络。`tests/` 套件位于项目的源代码仓库中(不包含在已发布的插件内);请从那里运行。从包目录中,您仍然可以语法检查每个模块:```
python3 -m py_compile *.py ui/*.py
python3 -m unittest discover -s tests   # from the source repository

The Binary Ninja-facing modules (context_builder, phase1, phase2) import cleanly without Binary Ninja (their API access is guarded) but require a running Binary Ninja to exercise.

针对 Binary Ninja 的模块(context_builder、phase1、phase2)可以在没有 Binary Ninja 的情况下正常导入(其 API 访问受到保护),但需要运行中的 Binary Ninja 才能实际执行。

Manual in-Binary-Ninja test

在 Binary Ninja 中手动测试

  1. Build a small vulnerable C program (e.g. one that strcpys argv[1] into a fixed stack buffer and calls system() on input). Compile with symbols to also exercise Phase 2.

  2. Start your local OpenAI-compatible server and set vulnfanatic.apiBaseUrl, vulnfanatic.apiKey, and vulnfanatic.model.

  3. Open the binary, run Start Scan, and confirm the dangerous calls are reported and double-clicking navigates to the call sites.

  4. 构建一个小的存在漏洞的 C 程序(例如,将 argv[1] strcpy 到一个固定栈缓冲区,并对输入调用 system())。编译时保留符号以同时测试 Phase 2。

  5. 启动本地的 OpenAI 兼容服务器,并设置 vulnfanatic.apiBaseUrl、vulnfanatic.apiKey 和 vulnfanatic.model。


Troubleshooting

故障排除

SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate — the HTTPS endpoint's certificate is fine, but Binary Ninja's bundled Python has no CA bundle to verify it against (common on macOS and in embedded Pythons; you'll see this with hosted endpoints like AWS Bedrock, Anthropic, Google, Azure). Fix with one of, in order of preference:

  • Install certifi into the Python Binary Ninja uses: pip install certifi. VulnFanatic-NG picks it up automatically.
  • Point at a CA bundle: set vulnfanatic.caBundlePath to a bundle file (or directory) — e.g. the path printed by python3 -m certifi, or /etc/ssl/cert.pem.
  • Last resort: turn off vulnfanatic.tlsVerify (only for a trusted/internal endpoint or a self-signed local server — this disables certificate checking).

SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate — HTTPS 端点的证书本身没有问题,但 Binary Ninja 自带的 Python 没有 CA 证书包来进行验证(在 macOS 和嵌入式 Python 中常见;在使用 AWS Bedrock、Anthropic、Google、Azure 等托管端点时会遇到)。按优先顺序选择以下一种方法修复:

  • 将 certifi 安装到 Binary Ninja 使用的 Python 中:pip install certifi。VulnFanatic-NG 会自动检测到它。
  • 指定 CA 证书包:设置 vulnfanatic.caBundlePath 指向一个证书包文件(或目录)——例如 python3 -m certifi 打印出的路径,或 /etc/ssl/cert.pem。
  • 最后的手段:关闭 vulnfanatic.tlsVerify(仅用于受信任的内部端点或自签名本地服务器——这会禁用证书检查)。

HTTP 400 ... tokenizer.chat_template is not set — the model you are serving has no chat template, so the /chat/completions endpoint cannot format the messages. VulnFanatic-NG automatically falls back to the /completions endpoint for the rest of the scan when it sees this error, so scanning continues. To avoid the first failed request entirely, set vulnfanatic.apiMode to completions. Alternatively, fix it server-side by serving a model that ships a chat template, or pass one to your server — e.g. for vLLM: --chat-template <template.jinja> (or use an -Instruct/-Chat model variant). The dedicated chat template usually gives better results than the flattened completions prompt.

HTTP 400 ... tokenizer.chat_template is not set — 您提供的模型没有聊天模板,因此 /chat/completions 端点无法格式化消息。VulnFanatic-NG 在遇到此错误时会自动回退到 /completions 端点进行后续扫描,因此扫描会继续。要完全避免第一次失败的请求,请将 vulnfanatic.apiMode 设置为 completions。另一种方法是在服务端修复:提供自带聊天模板的模型,或向服务器传递一个模板——例如对于 vLLM:--chat-template <template.jinja>(或使用 -Instruct/-Chat 模型变体)。专用聊天模板通常比扁平化的 completions 提示效果更好。

No JSON object found ... response looks truncated — the model's reply was cut off before the JSON finished. Two causes:

  • The scratchpad exceeded the response budget → raise vulnfanatic.maxResponseTokens.
  • More commonly: the prompt fills the model's context window, leaving no room to generate, so the reply stops after a few tokens no matter how high maxResponseTokens is. Local servers often have a small window (ollama defaults to num_ctx=2048!). Fix it by setting vulnfanatic.modelContextWindow to your server's window (e.g. ollama num_ctx, llama.cpp -c, vLLM --max-model-len) — VulnFanatic-NG then automatically caps the context it sends so prompt + response fit. Also keep vulnfanatic.maxResponseTokens reasonable (≈8192, not 65535) and/or raise the server's window. Tiny windows (≤8k) cannot hold the full interprocedural context; use a model/server configured for 32k+.

No JSON object found ... response looks truncated — 模型的回复在 JSON 完成之前被截断。有两种原因:

  • 草稿区超过了响应预算 → 调高 vulnfanatic.maxResponseTokens。
  • 更常见的情况: 提示填满了模型的上下文窗口,没有剩余空间用于生成,因此回复在几个 token 后就停止了,无论 maxResponseTokens 设置多高。本地服务器通常窗口较小(ollama 默认 num_ctx=2048!)。解决方法:将 vulnfanatic.modelContextWindow 设置为服务器的窗口大小(例如 ollama 的 num_ctx、llama.cpp 的 -c、vLLM 的 --max-model-len)——然后 VulnFanatic-NG 会自动限制其发送的上下文,使得提示+响应能放得下。同时保持 vulnfanatic.maxResponseTokens 合理(≈8192,而不是 65535)并/或调大服务器的窗口。太小的窗口(≤8k)无法容纳完整的过程间上下文;请使用配置为 32k+ 的模型/服务器。

IncompleteRead / Could not complete request ... after N attempt(s) — the server accepted the request but closed the connection before sending the full response. This almost always means the model server died or stalled mid-generation: out-of-memory (large context + long output), an internal/worker timeout, or a proxy resetting the connection. VulnFanatic-NG retries once automatically and then skips that site. Check the model server's own logs for the real cause; reducing vulnfanatic.maxContextTokens and/or vulnfanatic.maxResponseTokens, or giving the server more memory / a larger context window, usually resolves it.

IncompleteRead / Could not complete request ... after N attempt(s) — 服务器接受了请求,但在发送完整响应之前关闭了连接。这几乎总是意味着模型服务器在生成过程中崩溃或无响应:内存不足(大上下文+长输出)、内部/工作线程超时,或代理重置连接。VulnFanatic-NG 会自动重试一次,然后跳过该站点。检查模型服务器自身的日志以找到真正原因;减小 vulnfanatic.maxContextTokens 和/或 vulnfanatic.maxResponseTokens,或为服务器提供更多内存/更大的上下文窗口,通常可以解决此问题。

Limitations

局限性

  • Phase 2 is symbol-aware. On a stripped binary, name-based matches are unreliable, so by default only the string-evidence rules run (functions that reference tell-tale string constants are still auditable). Set vulnfanatic.phase2ForceEnable to also audit name-based matches, or vulnfanatic.phase2RequireSymbols=off. The symbol gate is a heuristic.

  • HLIL ↔ call-site mapping can fail; VulnFanatic-NG falls back to MLIL/assembly and notes the representation used per finding.

  • Verdicts are only as good as the model. Treat findings as leads for manual review, not ground truth.

  • Some local servers ignore or reject response_format=json_object; the client tolerates that and still extracts JSON. Disable vulnfanatic.sendJsonResponseFormat if your server rejects the parameter outright.

  • Phase 2 是符号感知的。 对于剥离了符号的二进制文件,基于名称的匹配不可靠,因此默认情况下只运行字符串证据规则(引用特征字符串常量的函数仍然可以被审计)。设置 vulnfanatic.phase2ForceEnable 也可以审计基于名称的匹配,或者将 vulnfanatic.phase2RequireSymbols 设为 off。符号检查是一种启发式方法。

  • HLIL ↔ 调用点映射可能失败;VulnFanatic-NG 会回退到 MLIL/汇编,并在每个发现中注明所使用的表示形式。

  • 判定结果的质量取决于模型。请将发现视为人工审核的线索,而非绝对事实。

  • 某些本地服务器会忽略或拒绝 response_format=json_object;客户端能容忍这种情况并仍然提取 JSON。如果您的服务器完全拒绝该参数,请禁用 vulnfanatic.sendJsonResponseFormat。

License

许可证

Apache-2.0 (© Martin Petran) — see plugin.json. Apache-2.0 (© Martin Petran) — 参见 plugin.json。

下载工具
  • 这些路径函数调用的其他函数的体(例如,对于 MAIN→ABCD→strcpy,还包含 MAIN 和 ABCD 在其他地方调用的函数),因为它们可能包含约束危险值的边界/验证检查(vulnfanatic.includeCallPathSiblings,在预算允许时填充),以及
  • 污染源提示(同一函数中调用的输入函数如 recv/read/getenv)。
  • 设置含义
    vulnfanatic.apiProvider要调用的 LLM 后端:openai(默认)、anthropic、google 或 azure。参见下方的 LLM 后端。所有提供者均通过 Python 标准库访问 — 无需 pip install。
    vulnfanatic.apiBaseUrl所选提供者的端点基础 URL(见下表)。默认值为 http://localhost:8080/v1。设置为字面值 TEST 以启用测试模式(见下方)。
    vulnfanatic.apiKeyAPI 密钥 / 承载令牌。对于本地服务器可以为空。会被环境变量 VULNFANATIC_API_KEY 或 OPENAI_API_KEY 覆盖。
    vulnfanatic.model必需(测试模式除外)。模型标识符(对于 azure,为部署名称)。
    vulnfanatic.apiMode仅 openai:chat(默认,/chat/completions)与 completions(单个扁平提示 — 适用于无聊天模板的基础/指令模型)。
    vulnfanatic.azureApiVersion仅 azure:api-version 查询参数(默认 2024-10-21)。
    提供者apiBaseUrl认证备注
    openai您的服务器,例如 http://localhost:8080/v1Authorization: BearerOpenAI 兼容的聊天/补全接口:本地 llama.cpp / ollama / vLLM、OpenAI 以及 AWS Bedrock 的 OpenAI 兼容端点。
    anthropic空白 → https://api.anthropic.comx-api-key + anthropic-versionClaude 消息 API(POST <base>/v1/messages)。temperature 不会被发送(当前 Claude 模型会拒绝它)。
    google空白 → https://generativelanguage.googleapis.comURL 中的 API 密钥Gemini generateContent(<base>/v1beta/models/<model>:generateContent)。
    azurehttps://<resource>.openai.azure.comapi-key 头Azure OpenAI;将 model 设置为部署名称,并将 azureApiVersion 设置为您 API 版本。
    vulnfanatic.callPathIncludeBodies
    vulnfanatic.callPathMaxBodies
    vulnfanatic.includeCallPathSiblings
    vulnfanatic.callPathSiblingMaxBodies
    vulnfanatic.includeDataTypes
    vulnfanatic.maxTypeDefs
    vulnfanatic.includeVariableDataflow
    vulnfanatic.dataflowMaxFunctions
    vulnfanatic.includeStackLayout
    vulnfanatic.scanIndirectCalls
    vulnfanatic.validationPass
    vulnfanatic.validatorModel
    vulnfanatic.validatorProvider
    vulnfanatic.validatorBaseUrl
    vulnfanatic.validatorApiKey
    vulnfanatic.minConfidence
    low
    medium
    high
    low
    vulnfanatic.flagUnparseableResponses
    UNKNOWN
    vulnfanatic.skipConstantArgCalls
    vulnfanatic.verdictReasoning
    concise
    full
    none
    concise
    vulnfanatic.runPhase1
    vulnfanatic.runPhase2
    vulnfanatic.runPhase3
    vulnfanatic.phase2RequireSymbols
    vulnfanatic.phase2ForceEnable
    vulnfanatic.tokenizerEncoding
    vulnfanatic.offlineBuildContext
    vulnfanatic.debugLogging
    vulnfanatic.debugAnonymous
    调试日志
    vulnfanatic.sendJsonResponseFormat
    vulnfanatic.tlsVerify
    vulnfanatic.caBundlePath
    CERTIFICATE_VERIFY_FAILED
    vulnfanatic.rulesPhase1Path
    vulnfanatic.rulesPhase2Path
    vulnfanatic.rulesPhase3Path
  • 打开二进制文件,运行 Start Scan,确认危险调用被报告,并且双击可导航到调用点。