基于大语言模型的自动化补丁差异分析:让漏洞挖掘效率飞跃

要点速览

研究人员开发了一个名为 diffalayze 的自动化补丁分析工具,结合大语言模型(LLM)实现二进制补丁差异的智能分析和安全风险评估。

核心技术亮点:

  • 工具链整合:基于 ghidriff 进行二进制差异分析,自动生成 Markdown 格式的差异报告
  • AI驱动分析:使用 Claude Opus 4.1GPT-5 等先进推理模型对补丁进行安全相关性评分和漏洞识别
  • 自动化流水线:支持多目标并行处理,可同时分析32个二进制文件的补丁差异

实战案例验证:
研究团队成功识别出 Windows SMB 驱动 mrxsmb.sys 中的整数溢出漏洞:

  • 漏洞位置RxCeEncryptData 函数在 SMBv3 加密过程中
  • 漏洞机制0xFFFFFF80 + 0x84 = 0x00000004 导致内存分配不足
  • 利用后果RtlCopyMdlToBuffer 尝试拷贝大量数据到小缓冲区,触发内核堆溢出和蓝屏
  • 修复方案:使用 RtlULongAdd 进行溢出检查,通过特性标志控制启用

技术特点:

  • 智能评分:LLM 自动分配 NONECRITICAL 的安全等级
  • 阈值触发:达到预设风险等级时自动执行通知脚本
  • Windows 集成:基于 Winbindex 项目自动下载和版本检测

局限性提醒:

  • • LLM 存在幻觉问题,容易产生误报
  • • Ghidra 反编译输出可能不准确,影响分析质量
  • • 高级推理模型(如 o3GPT-5 Thinking)表现明显优于基础模型

该工具为安全研究人员提供了高效的补丁分析自动化解决方案,特别适用于 Microsoft Patch Tuesday 等大规模补丁发布的快速筛查。

核心要点

补丁差异分析对于发现二进制文件两个版本之间的变化非常有用,但典型补丁日的分析量很大,手动分类需要大量时间。
本文展示的方法通过流水线处理二进制差异,提取相关变化,并让LLM对安全相关性进行评分和总结,使研究人员能够首先专注于有前景的部分。

仓库地址: https://github.com/SySS-Research/diffalayze

智能体无处不在

如今任何使用LLM的人都无法忽视工作流和智能体日益增长的作用。

智能体无处不在

借助合适的工具,许多日常任务都可以使用LLM进行简化和自动化。
我们想知道这个概念是否能帮助自动化二进制代码中的漏洞发现和可利用性分析。
这促使我们产生了构建AI驱动工作流的想法,该工作流分析二进制补丁差异并评估变化的潜在安全影响。

目标是自动突出显示有趣或潜在易受攻击的代码,
让安全研究人员能够将时间集中在重要的地方,
而不是花费数小时甚至数天进行手动逆向工程。

话不多说,让我们深入了解。

补丁差异分析

补丁差异分析是识别代码变化和理解补丁实际影响的强大技术。
虽然在有源代码访问权限的情况下进行差异分析相对简单,但在处理本机二进制文件时会变得更加困难。

幸运的是,存在几种工具来解决这个问题并支持二进制级别的差异分析,例如BinDiffDiaphoraghidriff
ghidriff(https://github.com/clearbluejar/ghidriff)是由clearbluejar(https://x.com/clearbluejar)开发的优秀开源工具,它结合多种技术来检测和可视化二进制文件中的代码差异。

使用这些工具,安全研究人员可以高效地识别漏洞的根本原因,发现可能引入新错误的变化,或检测所谓的静默补丁(对未公开披露的安全问题的修复)。
这些知识为漏洞利用开发、补丁有效性审查和有针对性的逆向工程提供支持。

然而,存在一个明显的瓶颈:大海捞针。
在典型的微软补丁星期二,数千行代码(LOC)在许多二进制文件中发生变化。
手动浏览所有差异非常耗时,这正是LLM可以帮助分类的地方。

工具:diffalayze

因此,我们编写了一个简单的工具,使用ghidriff自动化二进制文件的补丁差异分析,并实现了一个自定义AI工作流,用于基于LLM的差异分类。

Diffalayze示例用法

高级概述

diffalayze 的工作方式相当直接。

思路是使用所谓的fetch_script.py定义目标。
该脚本负责下载二进制文件或补丁的两个版本,验证版本自上次运行以来是否发生变化,并返回相应的文件。

一旦二进制文件准备就绪,基于Docker的ghidriff实例接管,施展魔法并生成几个差异文件。
然后将这些差异进一步处理为markdown格式的输出,使其更容易用LLM进行分析。

接下来,触发AI智能体并运行散布-聚集流水线:它映射差异块以产生每个块的分析,
然后使用选定的后端和语言模型(如OpenAI GPT-5)将它们合并为综合报告。
结果是一个markdown报告,包括分类摘要、补丁目的说明以及对任何已修复或新引入漏洞的分析。

LLM基于在差异中检测到的模式和其训练数据分配启发式安全评分和严重性级别(从NONE到CRITICAL)。
如果达到定义的阈值,将执行用户定义的操作,如触发脚本或发送通知。

总结一下,以下说明了此过程的高级概述:

流程概述

目标

在我们的分析中,我们专注于Windows内核驱动程序,如mrxsmb.sys
为了自动检查新版本并下载驱动程序二进制文件,我们使用了优秀的Winbindex项目。

为了简化这个过程,我们开发了一个辅助脚本,可以直接使用Winbindex项目数据库下载任何Windows二进制文件。
然后可以将此脚本集成到fetch_script.py中,如以下示例:

import urllib.request
from utils import winbindexer
from pathlib import Path

dbfile = "mrxsmb.sys.json.gz"
filename = "mrxsmb.sys"
windows_version = "11-24H2"

SCRIPT_DIR = Path(__file__).parent
tracking_file = SCRIPT_DIR / "version.log"

def download_file(url: str, dest: Path):
    try:
        urllib.request.urlretrieve(url, dest)
    except Exception as e:
        raise RuntimeError(f"[!] Download error: {e}")

def check_and_download():
    try:
        winbindexer.ensure_winbindex_repo()
        results = winbindexer.get_latest_symbol_urls(filename, dbfile, windows_version)

        if len(results) < 2:
            raise ValueError("[!] Could not find two version")

        new_version_url = results[0]["url"]
        old_version_url = results[1]["url"]

        if tracking_file.exists():
            last_known = tracking_file.read_text(encoding="utf-8").strip()
            if last_known == new_version_url:
                return False

        old_path = SCRIPT_DIR / f"old.{filename}"
        new_path = SCRIPT_DIR / f"new.{filename}"

        download_file(old_version_url, old_path)
        download_file(new_version_url, new_path)

        tracking_file.write_text(new_version_url + "\n", encoding="utf-8")

        return str(old_path), str(new_path)

    except (FileNotFoundError, ValueError, RuntimeError) as e:
        print(f"[!] Error: {e}")
        return "", ""

此示例由diffalyze调用,检查特定Windows构建(例如11-24H2)是否有新版本的mrxsmb.sys可用,如果有,则将其下载到目标目录。
它也可以作为获取其他Windows二进制文件的模板。

当并行分析多个目标时,diffalyze的真正优势变得明显。
例如,在我们的测试中,我们指定了多达32个二进制文件,这些文件被同时处理:

使用32个目标运行diffalayze

额外收获:我们观察到在分析较旧的Windows长期服务分支(LTSB)构建(如版本1607)时获得最佳结果。
这些版本的补丁通常只包含基本的安全修复,这导致更清洁的差异结果,并减少LLM必须处理的无关变化量。

其他目标呢?
原则上,任何二进制文件都可以使用diffalayze进行分析。
需要的是一个自定义的fetch_script.py,处理要分析的二进制文件的准备步骤。

演示

如上所述,我们使用diffalyze分析Windows内核驱动程序,如mrxsmb.sys
以下示例显示了如何使用diffalyze分析此二进制文件。

diffalyze可以按如下方式执行:

python3 diffalayze.py all -f -a -lv -lb anthropic -lm claude-opus-4-1 -llt HIGH -ltc ../notify.sh

参数说明:

  • all:将覆盖targets目录中的所有目标
  • -f (--force):强制差异分析,即使找不到二进制文件的新版本
  • -a (--analyze):在差异分析后启用LLM分析
  • -lv (--llm-verbose):LLM分析的详细输出
  • -lb (--llm-backend):LLM后端,例如anthropic、openai、ollama
  • -lm (--llm-model):语言模型,例如claude-opus-4-1或gpt-5
  • -llt (--llm-level-threshold):触发外部脚本的严重性阈值
  • -ltc (--llm-trigger-cmd):如果达到指定阈值要执行的脚本

执行的输出如下所示:

示例运行

由于指定了外部脚本在安全级别阈值大于或等于HIGH时触发,并且LLM实际上将两个目标评为CRITICAL
脚本被执行并发送了通知:

关于目标评估的通知

最终的分析报告如下所示:

示例结果(点击展开)

# 摘要

- 解决的最高风险:RxCeEncryptData中的功能门控修复添加了溢出检查的大小计算,以防止SMB加密期间可能导致内核堆溢出的整数溢出(CWE-190 → CWE-122)。如果功能被禁用,不安全路径仍然存在。
- 重要的加固:MRxSmbCreateSrvCall引入了功能门控拒绝类似凭据编组的服务器名称,以防止身份验证混淆(CWE-20,CWE-287),输入规范化,显式可用性检查,安全分配,改进的遥测和确定性清理,以减少陈旧状态和内存风险(CWE-664)。
- 剩余风险:两个主要缓解措施都由功能标志控制;禁用这些功能的部署保留先前的行为。

# 详细发现

- RxCeEncryptData(加密路径)
  - 功能门控溢出检查大小调整
    - 当功能启用时,用RtlULongAdd检查替换头部/有效负载大小调整的未检查32位加法。分配现在使用验证的大小。
    - 防止分配不足,然后复制/加密param_4字节。
  - 类型纠正和参数处理
    - 将长度参数类型从int*更改为uint*,以与预期的ULONG语义对齐,避免有符号长度陷阱(CWE-681)。
    - 修复RtlCopyMdlToBuffer"复制的字节数"输出参数为专用局部变量,避免破坏长度参数。
- MRxSmbCreateSrvCall(连接设置路径)
  - 早期拒绝和遥测
    - 重新排序早期0x400标志检查以立即记录并返回特定的NTSTATUS;提高清晰度而不改变安全态势。
  - 子重定向器启动和预声明
    - 在哨兵上显式启动子重定向器并预声明服务器调用,以在连接前减少不一致状态。
  - 输入规范化
    - 在进一步处理之前从服务器名称中修剪前导反斜杠(CWE-20)。
  - 功能门控凭据编组拒绝
    - 如果启用,在服务器名称上调用CredUnmarshalTargetInfo,并使用STATUS_INVALID_PARAMETER(0xc000000d)拒绝任何识别为编组数据的内容。阻止类似cred-marshal的输入到达身份验证路径(CWE-20,CWE-287)。
  - 可用性、分配和有界复制
    - 查询服务器可用性,显式构造服务器条目,分配大小为UNICODE_STRING长度的缓冲区,并使用RtlCopyUnicodeString进行有界复制(减少CWE-119/120暴露)。
  - 失败时清理
    - 重置状态,取消引用服务器条目,并在错误返回时释放分配(CWE-664)。

# 可利用性和影响

- RxCeEncryptData中的整数溢出→堆溢出(最关键)
  - 之前:未检查的32位加法(param_4 + 常量)可能回绕,导致ExAllocatePoolWithTag分配不足,而RtlCopyMdlToBuffer/SmbCryptoEncrypt在param_4字节上操作,启用内核池溢出。
  - 之后:启用功能后,RtlULongAdd验证两个加法并在溢出时中止。
  - 可利用性:取决于param_4的上游边界。如果param_4可以被攻击者影响且很大,补丁前代码存在风险。补丁后安全性取决于功能标志是否启用。
- MRxSmbCreateSrvCall中类似凭据编组的服务器名称
  - 风险:类似编组目标信息的服务器名称如果被凭据API解释,可能导致身份验证混淆或误用。
  - 缓解:启用时,CredUnmarshalTargetInfo用作门控;识别的编组形式被STATUS_INVALID_PARAMETER拒绝。
  - 可利用性:在攻击者影响UNC/DFS名称的情况下是现实的;有效性取决于功能启用。
- 资源生命周期和清理
  - 风险:没有失败时的显式拆卸,陈旧指针/泄漏可能累积,在错误搅动下增加UAF/不一致风险。
  - 缓解:显式状态归零、取消引用和释放路径减少与生命周期相关的问题。主要是稳定性/DoS加固。
- 较小问题
  - RxCeEncryptData中的类型纠正和输出参数修复减少逻辑/别名风险;直接可利用性低。
  - 遥测更改改善诊断;在显示的片段中没有明显的敏感数据暴露。

剩余/新风险:
- 功能标志依赖:两个主要缓解措施都由功能描述符上的EvaluateCurrentState控制。如果在某些配置中禁用,原始风险仍然存在。
- 来自输入大小服务器名称的大但有界分配可能导致内存压力(低DoS风险)。
- 部分规范化仅修剪单个前导反斜杠;考虑到cred-marshal检查的目的,不太可能与安全相关。

# 下一步复现分析步骤

- 验证功能标志行为
  - 识别并切换相关功能描述符:
    - RxCeEncryptData大小检查:g_Feature_2962494776_56195954_FeatureDescriptorDetails。
    - MRxSmbCreateSrvCall cred-marshal门控:g_Feature_2181565755_56614078_FeatureDescriptorDetails。
  - 测试启用和禁用状态以确认代码路径和结果。

- 复现和验证整数溢出修复(RxCeEncryptData)
  - 功能禁用时,使用会导致param_4 + 0x34或+0x84中32位加法溢出的大param_4值驱动RxCeEncryptData;观察分配大小与复制长度行为。
  - 功能启用时,确认RtlULongAdd返回错误,函数以记录的失败代码(-0x3ffffbd5)退出而不是继续。
  - 确认IoAllocateMdl使用纠正的无符号长度,清理在失败时将长度归零。

- 练习凭据编组拒绝(MRxSmbCreateSrvCall)
  - 提供CredUnmarshalTargetInfo识别为编组目标信息的服务器名称缓冲区。
    - 功能启用时,期望STATUS_INVALID_PARAMETER立即失败和反映状态的WPP遥测。
    - 功能禁用时,确认请求通过此点继续。
  - 通过提供带前导反斜杠的名称并检查用于编组检查的调整指针/长度来验证输入规范化。

- 验证失败路径清理(MRxSmbCreateSrvCall)
  - 诱发分配失败(例如,强制服务器名称或阶段上下文的ExAllocatePoolWithTag失败)并验证:
    - lVar3 + 0x20处的状态被归零。
    - 服务器条目被取消引用。
    - 阶段上下文缓冲区被释放。
    - 返回正确的NTSTATUS,遥测记录状态。

- 有界复制的合理性检查
  - 对于服务器名称分配/复制,提供变化的UNICODE_STRING长度(包括零和最大典型大小)并验证分配匹配源长度,RtlCopyUnicodeString在边界内写入。

这些步骤将确认缓解措施,暴露任何遗留的功能门控差距,并验证新错误路径的健壮性。

---

## 安全相关性评估
**级别:** CRITICAL
**评分:** 85
**摘要:** 报告识别了RxCeEncryptData中整数溢出的功能门控修复,该溢出可能在SMB加密期间导致内核堆溢出,并在MRxSmbCreateSrvCall中添加加固以拒绝类似凭据编组的服务器名称。由于两个缓解措施都在功能标志后面,如果功能被禁用,先前的易受攻击行为可能持续存在。

实际差异(点击展开)

--- MRxSmbCreateSrvCall
+++ MRxSmbCreateSrvCall
@@ -1,16 +1,162 @@

 uint MRxSmbCreateSrvCall(undefined8 param_1,longlong param_2)

 {
-  uint uVar1;
+  short *psVar1;
+  short sVar2;
+  longlong lVar3;
+  longlong lVar4;
+  ushort *puVar5;
+  undefined4 uVar6;
+  undefined4 uVar7;
+  undefined4 uVar8;
+  undefined8 uVar9;
+  bool bVar10;
+  uint uVar11;
+  int iVar12;
+  undefined7 extraout_var;
+  longlong lVar13;
+  short *_Dst;
+  short *psVar14;
+  short *psVar15;
+  short *local_res8;
+  ushort local_38;
+  ushort uStack_36;
+  ushort uStack_34;
+  ushort uStack_32;
+  short *psStack_30;

-  if ((*(uint *)(*(longlong *)(param_2 + 0x20) + 0x78) & 0x400) == 0) {
-    uVar1 = SmbCeCreateSrvCall(param_2);
-    return uVar1;
+  if ((*(uint *)(*(longlong *)(param_2 + 0x20) + 0x78) & 0x400) != 0) {
+    if ((Microsoft_Windows_SMBClientEnableBits & 1) != 0) {
+      Template_qqq(param_1,&CreateSrvCallError,*(longlong *)(param_2 + 0x20) + 0x18c,0xc00000be);
+    }
+    return 0xc00000be;
   }
+  lVar3 = *(longlong *)(param_2 + 0x108);
+  _Dst = (short *)0x0;
+  lVar4 = *(longlong *)(param_2 + 0x20);
+  if (*(longlong *)(lVar3 + 0xd8) == 0xffffffff) {
+    StartSubRedirectorForDialect(MRxSmbDeviceObject,1);
+  }
+  uVar11 = SubRdrPreClaimSrvCall(lVar3,param_2);
+  psVar15 = _Dst;
+  psVar14 = _Dst;
+  if (uVar11 == 0xc0000016) {
+    puVar5 = *(ushort **)(lVar3 + 0x40);
+    local_38 = *puVar5;
+    uStack_36 = puVar5[1];
+    uStack_34 = puVar5[2];
+    uStack_32 = puVar5[3];
+    psStack_30 = *(short **)(puVar5 + 4);
+    if ((1 < local_38) && (*psStack_30 == 0x5c)) {
+      psStack_30 = psStack_30 + 1;
+      local_38 = local_38 - 2;
+      uStack_36 = uStack_36 - 2;
+    }
+    bVar10 = EvaluateCurrentState(&g_Feature_2181565755_56614078_FeatureDescriptorDetails);
+    if ((int)CONCAT71(extraout_var,bVar10) != 0) {
+      iVar12 = CredUnmarshalTargetInfo(psStack_30,local_38,0,0);
+      uVar11 = 0xc000000d;
+      if (iVar12 != -0x3ffffff3) {
+        if ((((undefined8 **)WPP_GLOBAL_Control != &WPP_GLOBAL_Control) &&
+            ((*(uint *)((longlong)WPP_GLOBAL_Control + 0x2c) & 1) != 0)) &&
+           (*(char *)((longlong)WPP_GLOBAL_Control + 0x29) != '\0')) {
+          WPP_SF_Z(WPP_GLOBAL_Control[3],0xb,&WPP_2876989b72e03b5952b18ed47e9e9657_Traceguids,
+                   &local_38);
+        }
+        goto LAB_0;
+      }
+    }
+    uVar11 = SmbCeQueryServerAvailability(&local_38,1);
+    if (-1 < (int)uVar11) {
+      local_res8 = (short *)0x0;
+      uVar11 = SmbCeConstructServerEntry(lVar3,(longlong *)&local_res8);
+      psVar15 = local_res8;
+      psVar14 = (short *)0x0;
+      if (uVar11 == 0) {
+        uVar9 = *(undefined8 *)(param_2 + 0x58);
+        lVar13 = *(longlong *)(param_2 + 0x70);
+        *(undefined8 *)(local_res8 + 0x70) = *(undefined8 *)(param_2 + 0x50);
+        *(undefined8 *)(local_res8 + 0x74) = uVar9;
+        uVar6 = *(undefined4 *)(param_2 + 100);
+        uVar7 = *(undefined4 *)(param_2 + 0x68);
+        uVar8 = *(undefined4 *)(param_2 + 0x6c);
+        *(undefined4 *)(local_res8 + 0x78) = *(undefined4 *)(param_2 + 0x60);
+        *(undefined4 *)(local_res8 + 0x7a) = uVar6;
+        *(undefined4 *)(local_res8 + 0x7c) = uVar7;
+        *(undefined4 *)(local_res8 + 0x7e) = uVar8;
+        *(undefined8 *)(local_res8 + 0x80) = *(undefined8 *)(param_2 + 0x70);
+        if (lVar13 != 0) {
+          RxReferenceCredential();
+        }
+        psVar14 = _Dst;
+        if (*(longlong *)(psVar15 + 0x80) != 0) {
+          psVar14 = *(short **)(*(longlong *)(psVar15 + 0x80) + 0x30);
+        }
+        psVar15[0x141] = 0;
+        psVar1 = psVar15 + 0x140;
+        *psVar1 = 0;
+        psVar15[0x144] = 0;
+        psVar15[0x145] = 0;
+        psVar15[0x146] = 0;
+        psVar15[0x147] = 0;
+        if ((psVar14 != (short *)0x0) && (*psVar14 != 0)) {
+          lVar13 = ExAllocatePoolWithTag(0x200,*psVar14,0x734d6d53);
+          *(longlong *)(psVar15 + 0x144) = lVar13;
+          if (lVar13 == 0) {
+            uVar11 = 0xc000009a;
+            goto LAB_0;
+          }
+          sVar2 = *psVar14;
+          psVar15[0x141] = sVar2;
+          *psVar1 = sVar2;
+          RtlCopyUnicodeString(psVar1,psVar14);
+        }
+        _Dst = (short *)ExAllocatePoolWithTag(0x200,0x48,0x734d6d53);
+        if (_Dst == (short *)0x0) {
+          uVar11 = 0xc000009a;
+          goto LAB_0;
+        }
+        memset(_Dst,0,0x48);
+        *(longlong *)(_Dst + 8) = param_2;
+        *(code **)_Dst = SmbCeCompleteSrvCallConstructionPhase2;
+        *(short **)(_Dst + 0x10) = _Dst + 0x18;
+        *(short **)(_Dst + 0xc) = psVar15;
+        _Dst[0x14] = 0;
+        _Dst[0x15] = 0;
+        _Dst[0x16] = 0;
+        _Dst[0x17] = 0;
+        uVar11 = SmbCepEstablishServerConnection(psVar15,_Dst,_Dst + 0x18);
+        psVar14 = _Dst;
+      }
+    }
+  }
+  else if ((((undefined8 **)WPP_GLOBAL_Control != &WPP_GLOBAL_Control) &&
+           ((*(uint *)((longlong)WPP_GLOBAL_Control + 0x2c) & 0x40) != 0)) &&
+          (1 < *(byte *)((longlong)WPP_GLOBAL_Control + 0x29))) {
+    WPP_SF_qZ(WPP_GLOBAL_Control[3],10,&WPP_2876989b72e03b5952b18ed47e9e9657_Traceguids,lVar3,
+              *(undefined2 **)(lVar3 + 0x40));
+  }
+  _Dst = psVar14;
+  if (-1 < (int)uVar11) {
+    return uVar11;
+  }
+LAB_0:
   if ((Microsoft_Windows_SMBClientEnableBits & 1) != 0) {
-    Template_qqq(param_1,&CreateSrvCallError,*(longlong *)(param_2 + 0x20) + 0x18c,0xc00000be);
+    Template_qqq(WPP_GLOBAL_Control,&CreateSrvCallError,lVar4 + 0x18c,uVar11);
   }
-  return 0xc00000be;
+  if ((((undefined8 **)WPP_GLOBAL_Control != &WPP_GLOBAL_Control) &&
+      ((*(uint *)((longlong)WPP_GLOBAL_Control + 0x2c) & 1) != 0)) &&
+     (*(char *)((longlong)WPP_GLOBAL_Control + 0x29) != '\0')) {
+    WPP_SF_qL(WPP_GLOBAL_Control[3],0xc,&WPP_2876989b72e03b5952b18ed47e9e9657_Traceguids,lVar3);
+  }
+  *(undefined8 *)(lVar3 + 0x20) = 0;
+  if (psVar15 != (short *)0x0) {
+    SmbCeDereferenceServerEntryEx((longlong)psVar15,'\0');
+  }
+  if (_Dst != (short *)0x0) {
+    ExFreePoolWithTag(_Dst,0);
+  }
+  return uVar11;
 }

--- RxCeEncryptData
+++ RxCeEncryptData
@@ -1,44 +1,57 @@

 int RxCeEncryptData(undefined8 param_1,undefined8 *param_2,undefined8 param_3,ULONG param_4,
-                   longlong *param_5,int *param_6)
+                   longlong *param_5,uint *param_6)

 {
   undefined4 *puVar1;
   PUCHAR pUVar2;
-  int *piVar3;
+  bool bVar3;
   int iVar4;
-  longlong lVar5;
+  undefined7 extraout_var;
+  undefined8 uVar5;
   longlong lVar6;
+  longlong lVar7;
+  uint local_38 [2];
+  undefined1 local_30 [8];

-  piVar3 = param_6;
-  *param_6 = param_4 + 0x34;
-  lVar5 = ExAllocatePoolWithTag(0x200,param_4 + 0x84,0x66426d53);
-  if (lVar5 == 0) {
+  bVar3 = EvaluateCurrentState(&g_Feature_2962494776_56195954_FeatureDescriptorDetails);
+  if ((int)CONCAT71(extraout_var,bVar3) == 0) {
+    *param_6 = param_4 + 0x34;
+    local_38[0] = param_4 + 0x84;
+  }
+  else {
+    uVar5 = RtlULongAdd(0x34,param_4,param_6);
+    if (((int)uVar5 < 0) || (uVar5 = RtlULongAdd(0x50,*param_6,local_38), (int)uVar5 < 0)) {
+      return -0x3ffffbd5;
+    }
+  }
+  lVar6 = ExAllocatePoolWithTag(0x200,local_38[0],0x66426d53);
+  if (lVar6 == 0) {
     iVar4 = -0x3fffff66;
   }
   else {
-    puVar1 = (undefined4 *)(lVar5 + 0x50);
-    *(undefined8 *)(lVar5 + 0x7c) = param_1;
-    pUVar2 = (PUCHAR)(lVar5 + 0x84);
+    puVar1 = (undefined4 *)(lVar6 + 0x50);
+    *(undefined8 *)(lVar6 + 0x7c) = param_1;
+    pUVar2 = (PUCHAR)(lVar6 + 0x84);
     *puVar1 = 0x424d53fd;
-    *(ULONG *)(lVar5 + 0x74) = param_4;
-    *(undefined4 *)(lVar5 + 0x78) = 0x10000;
-    RtlCopyMdlToBuffer(param_3,0,pUVar2,param_4,¶m_6);
+    *(ULONG *)(lVar6 + 0x74) = param_4;
+    *(undefined4 *)(lVar6 + 0x78) = 0x10000;
+    RtlCopyMdlToBuffer(param_3,0,pUVar2,param_4,local_30);
     iVar4 = SmbCryptoEncrypt(param_2,(longlong)puVar1,pUVar2,param_4,pUVar2);
     if (-1 < iVar4) {
-      lVar6 = IoAllocateMdl(puVar1,*piVar3,0,0,0);
-      *param_5 = lVar6;
-      if (lVar6 != 0) {
-        MmBuildMdlForNonPagedPool(lVar6);
+      lVar7 = IoAllocateMdl(puVar1,*param_6,0,0,0);
+      *param_5 = lVar7;
+      if (lVar7 != 0) {
+        MmBuildMdlForNonPagedPool(lVar7);
         *(ushort *)(*param_5 + 10) = *(ushort *)(*param_5 + 10) | 0x1000;
         return 0;
       }
       iVar4 = -0x3fffff66;
     }
-    ExFreePoolWithTag(lVar5,0x66426d53);
+    ExFreePoolWithTag(lVar6,0x66426d53);
   }
   *param_5 = 0;
-  *piVar3 = 0;
+  *param_6 = 0;
   return iVar4;
 }

现在有趣的部分开始了,我们验证结果并深入挖掘二进制文件…

案例研究:整数溢出和基于堆的缓冲区溢出

在上面的示例中,突出显示了RxCeEncryptData(带加密的SMBv3)中可能的整数溢出/回绕,后来导致基于堆的缓冲区溢出。
让我们手动分析补丁。

查看mrxsmb.sys的较旧版本,我们快速发现了溢出。
它源于调用者传入的第四个参数:

整数溢出

现在,让我们看看这个错误的实际情况:

下图说明了在SMBv3加密过程中对RxCeEncryptData的调用,其中有效负载长度0xFFFFFF80R9寄存器中传递。

调用RxCeEncryptData

发生整数溢出(0xFFFFFF80 + 0x84 = 0x00000004),该值用作ExAllocatePoolWithTag的第二个参数(RDX):

内存分配

然后RtlCopyMdlToBuffer尝试将0xFFFFFF80字节(R9)复制到先前分配的小缓冲区中:

RtlCopyMdlToBuffer

最后,发生预期的页面错误。

系统错误

蓝屏死机

很好,我们的自动化方法标记了这个错误。
在较新版本中,我们快速识别了修复:

修复的整数溢出

最终,问题得到了修复,我们假设这是CVE-2025-32718(https://msrc.microsoft.com/update-guide/en-US/advisory/CVE-2025-32718)的根本原因。

注意事项

虽然成功识别了已修复的错误,特别是与内存相关的错误,但LLM也倾向于产生幻觉并生成误报。
这特别发生在模型试图检测补丁可能引入的新漏洞时。
尽管这是基于AI的静态代码分析的常见限制,但当提交的代码缺乏足够上下文时,这种情况变得更加明显。

另一个问题是反编译输出的可靠性。
该工具使用Ghidra伪代码,这可能不准确。
常见陷阱包括错误的返回值、有符号与无符号不匹配导致比较翻转,以及误解的结构或位字段。

在选择模型方面,我们观察到使用高级推理模型(如o3、GPT-5(Thinking)或Opus 4.1)时结果明显更好,包括更多细节、带代码引用的更清晰解释和更少的误报。

结论

我们成功采用了自动化补丁差异方法,结合AI驱动的工作流来识别静默修复和已知漏洞或错误。

在发布时,这种方法已在两个补丁星期二期间用于32个Windows驱动程序目标。
尽管存在各种误报和偶尔的幻觉,该工具没有发现任何由补丁本身引入的先前未知漏洞。

这再次强调,仅依赖LLM而没有适当验证是有限制的。

尽管如此,在不久的将来实现这一目标似乎是可以达到的。
随着经验的增长和更广泛的结果集,我们将能够微调提示,在需要时提供额外的代码上下文,并可能实现专门的验证机制。

学习资源

如果你是也准备转行学习网络安全(黑客)或者正在学习,这里开源一份360智榜样学习中心独家出品《网络攻防知识库》,希望能够帮助到你

知识库由360智榜样学习中心独家打造出品,旨在帮助网络安全从业者或兴趣爱好者零基础快速入门提升实战能力,熟练掌握基础攻防到深度对抗。

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

在这里插入图片描述

一、知识库价值

深度: 本知识库超越常规工具手册,深入剖析攻击技术的底层原理与高级防御策略,并对业内挑战巨大的APT攻击链分析、隐蔽信道建立等,提供了独到的技术视角和实战验证过的对抗方案。

广度: 面向企业安全建设的核心场景(渗透测试、红蓝对抗、威胁狩猎、应急响应、安全运营),本知识库覆盖了从攻击发起、路径突破、权限维持、横向移动到防御检测、响应处置、溯源反制的全生命周期关键节点,是应对复杂攻防挑战的实用指南。

实战性: 知识库内容源于真实攻防对抗和大型演练实践,通过详尽的攻击复现案例、防御配置实例、自动化脚本代码来传递核心思路与落地方法。

二、 部分核心内容展示

360智榜样学习中心独家《网络攻防知识库》采用由浅入深、攻防结合的讲述方式,既夯实基础技能,更深入高阶对抗技术。

在这里插入图片描述

360智榜样学习中心独家《网络攻防知识库》采用由浅入深、攻防结合的讲述方式,既夯实基础技能,更深入高阶对抗技术。

内容组织紧密结合攻防场景,辅以大量真实环境复现案例、自动化工具脚本及配置解析。通过策略讲解、原理剖析、实战演示相结合,是你学习过程中好帮手。

1、网络安全意识

img

2、Linux操作系统

img

3、WEB架构基础与HTTP协议

img

4、Web渗透测试

img

5、渗透测试案例分享

img

6、渗透测试实战技巧

图片

7、攻防对战实战

图片

8、CTF之MISC实战讲解

图片

三、适合学习的人群

基础适配人群

  1. 零基础转型者‌:适合计算机零基础但愿意系统学习的人群,资料覆盖从网络协议、操作系统到渗透测试的完整知识链‌;
  2. 开发/运维人员‌:具备编程或运维基础者可通过资料快速掌握安全防护与漏洞修复技能,实现职业方向拓展‌或者转行就业;
  3. 应届毕业生‌:计算机相关专业学生可通过资料构建完整的网络安全知识体系,缩短企业用人适应期‌;

能力提升适配

1、‌技术爱好者‌:适合对攻防技术有强烈兴趣,希望掌握漏洞挖掘、渗透测试等实战技能的学习者‌;

2、安全从业者‌:帮助初级安全工程师系统化提升Web安全、逆向工程等专项能力‌;

3、‌合规需求者‌:包含等保规范、安全策略制定等内容,适合需要应对合规审计的企业人员‌;

因篇幅有限,仅展示部分资料,完整版的网络安全学习资料已经上传CSDN,朋友们如果需要可以在下方CSDN官方认证二维码免费领取【保证100%免费】

‌;

因篇幅有限,仅展示部分资料,完整版的网络安全学习资料已经上传CSDN,朋友们如果需要可以在下方CSDN官方认证二维码免费领取【保证100%免费】

在这里插入图片描述

文章来自网上,侵权请联系博主

Logo

更多推荐