首页
社区
课程
招聘
[原创]客户端缓存文件系统驱动csc.sys漏洞CVE-2026-26176分析与复现
发表于: 17小时前 736

[原创]客户端缓存文件系统驱动csc.sys漏洞CVE-2026-26176分析与复现

王cb 活跃值
13
17小时前
736

引用

这篇文章的目的是介绍Windows客户端缓存文件系统驱动程序(csc.sys)特权提升漏洞CVE-2026-26176分析与复现.

目录

简介

CVE-2026-26176漏洞公告发布于2026年4月,文章结合了逆向代码及调试结果分析了特权提升漏洞CVE-2026-26176的利用过程和漏洞成因.

复现环境

Windows 11 26h2 canary preview

CVE-2026-26176漏洞原理简介

漏洞的主要原因存在于csc.sys驱动函数CscQueryDirectory处理客户端调用程序NtQueryDirectoryFile相关文件操作存在用户态竞争条件TOCTOU篡改IRP缓冲区数据导致的内核内存操作越界读写的特权提升漏洞.

CVE-2026-26176漏洞分析

csc.sys驱动程序理论上是一种挂载于现有SMB或其他网络微型重定向器驱动程序(network mini-redirector driver)实现用于同步的缓存文件系统驱动程序.

NTSTATUS RxRegisterMinirdr(
  [out]     OUT PRDBSS_DEVICE_OBJECT *DeviceObject,
  [in, out] IN OUT PDRIVER_OBJECT    DriverObject,
  [in]      IN PMINIRDR_DISPATCH     MrdrDispatch,
  [in]      IN ULONG                 Controls,
  [in]      IN PUNICODE_STRING       DeviceName,
  [in]      IN ULONG                 DeviceExtensionSize,
  [in]      IN DEVICE_TYPE           DeviceType,
  [in]      IN ULONG                 DeviceCharacteristics
);

所有的Minirdr驱动都有一个自己的PMINIRDR_DISPATCH分发函数结构体通过RxRegisterMinirdr注册用于处理对应的不同smb消息协议格式回调,Minirdr驱动可以是基于smb协议或挂载于smb协议比如(smb over quic,webclient协议)微软linux wsl的Plan 9文件系统,rdp协议客户端等文件系统等.相关协议绑定可以在注册表HKLM\System\CurrentControlSet\Control\NetworkProvider\Order查询当前操作系统支持的协议类型.

Dos Path Full Path NT Path
\\server\share\ABC\DEF \\server\share\ABC\DEF \??\UNC\server\share\ABC\DEF
\\server \\server \??\UNC\server
\\server\share \\server\share \??\UNC\server\share
\\server\share\ABC.<SP>. \\server\share\ABC \??\UNC\server\share\ABC
//server/share/ABC/DEF \\server\share\ABC\DEF \??\UNC\server\share\ABC\DEF
\\server\share\ABC\..\XYZ \\server\share\XYZ \??\UNC\server\share\XYZ
\\server\share\ABC\..\..\.. \\server\share \??\UNC\server\share

Minirdr驱动的路径统称为UNC路径它的应用层路径Dos Path和 NT Path可以根据如上表格表示,每种协议都有自己的Minirdr接口实现,所有文件类型均为MUP文件系统的子对象,但底层通信数据与smb协议文档中的消息规范相同.csc文件系统挂载于现有Minirdr文件系统之上,用于同步缓存数据,可以通过相同的UNC路径和一组eabuffer调用NtCreateFile创建csc文件对象,MUP协议入口例程成会在CscEaParseEa判断是否是csc文件系统的eabuffer,如果是进入CscCreate调用将csc设备CscDeviceObject挂载底层设备之上并调用的RxSetFcbDispatchTable重写PMINIRDR_DISPATCH结构体分发表,完成RxFsdDispatch处理后转发至底层文件系统分发表,底层文件系统通信实现仍由底层文件系统自身实现.eabuffer数据可以通过逆向应用层dll的功能得到或对CscCreate下内核断点从irp的SytemBuffer上下文字段获取,长度为0x1c字节,但不能是任意值,其中的每个字节均会产生不同的效果有兴趣的读者可以自己尝试下,在win11及以后的操作系统允许以smb quic的协议方式绑定本地smb文件共享端口,可以使用net.exe use \UNC路径 /TRANSPORT:QUIC /SKIPCERTCHECK这样的命令创建一个smb挂载路径,同样支持绑定上层csc文件文件系统.笔者的Smb Quic重放工具实现了大部分功能,无需借助远程linux服务器,需要修复的一点是csc调用了RxQueryNetRootCachingMode底层函数,判断TREE_CONNECT消息的返回参数ShareFlags 时候是否是可以支持缓存文件类型,这里只需要将ShareFlags类型设置成不包含TreeConnectResponse.ShareFlags.NO_CACHING位即可通过验证.csc文件系统实现了一套内置的缓存文件管理系统存储在一个自带的隐藏数据库中,类似接口由PinEntry系列函数实现,可以通过应用层cscapi.dll或者csc服务com组件接口实现,但底层实现相同,均是由csc的文件对象(Mup设备名加上相对的文件路径)NtFsControlFile函数实现,支持的功能包括添加缓存文件CSC_FSCTL_OPERATION_SET_PIN删除缓存文件CSC_FSCTL_OPERATION_DELETE_PIN查询缓存状态等功能.文件系统FsControl操作会分发到 CscDclInternalFsControl处理,csc对不同的控制码做了权限管理,并不是所有的控制码都可以被普通用户调用,以下权限验证过程CscDclpInitializeFsctlContext伪代码显示,有的操作仅限管理员,有的对文件访问标志做限制,有的仅限于csc服务调用,有的判断是否为发起进程操作等.操作码对应的字符串名称可以在CscDclpGetFsctlOperationString找到,笔者用c#演示了提取普通用户可以操作的控制码.在windbg调试器对配置元数据转储后.

_int64 __fastcall CscDclpInitializeFsctlContext(
        __int64 a1,
        PRX_CONTEXT a2,
        char admintoken,
        char AccessCheck,
        char isadmin)
{

 v19 = *(int *)((char *)&dword_14003C798 + CscFsctlOperation);
  if ( (v19 & 2) != 0 && !AccessCheck )
  {
    return  0xC0000022;   
  }
  // 00000000000008f6
  if ( (v19 & 4) != 0 && !isadmin )
  {
    return  0xC0000022;   
  }
  if ( (v19 & 8) != 0 && !admintoken && !AccessCheck )
  {
    return 0xC0000022;   
  }  
  //.writemem C:\\access.bin fffff803`6adfc798 fffff803`6adfd798
  //笔者用c#演示了提取普通用户可以操作的控制码
 int opoffset = CscFsctlOperation << 6;
int acc = EndianUtilities.ToInt32LittleEndian(dword_14003C798, opoffset);
CscFsctlOperationCheck chk = (CscFsctlOperationCheck)acc;
if (!chk.HasFlag(CscFsctlOperationCheck.Admin)&&!chk.HasFlag(CscFsctlOperationCheck.CscSvcOnly) && !chk.HasFlag(CscFsctlOperationCheck.AdminAccessCheck))
{
    Console.WriteLine(CscFsctlOperation + ":=>" + chk);
}
                

csc驱动除了存在对文件对象操作,还存在对目录进行操作,可以使用\Device\Csc..\ + RemoteDirName这样的路径创建对csc目录对象发起操作,比如NtQueryDirectoryFile函数,这个函数会在CscQueryDirectory先调用CscUpdateAndCaptureConnectionStateEx查询当前客户端文件连接的状态,微软没有官方的文档描述状态的每个标志位是什么作用.笔者只能通过调试和逆向绕过错误的控制流路径到达漏洞点函数,如下伪代码显示PRX_CONTEXT指针存在一个pRelevantSrvOpen字段,逆向发现它的+38偏移量字段存在一个链表结构指向csc目录包含的文件对象链表,其实csc文件系统也是基于Minirdr规范,每个结构体的前2个字节为NODE_TYPE_CODE,这个字段的存在可以标识结构体的类型,可以找到微软官方api的头文件或通过这个类型2字节值搜索匹配从csc.sys或依赖驱动找到具体类型,之后代码显示如果这个连接状态不包含0x20位会进入错误例程处理,所以这个位必须被置位,也就是需要存在一个有效的pRelevantSrvOpen关联的PIN文件对象,实现方法只需要在NtQueryDirectoryFile发起前调用PIN系列参数构造一个有效的缓存文件对象,也可以在调试器查看这个类型,和通过刚才说的方法定位到构造过程代码,如果PIN失败先调用删除PIN,然后重试如果仍然失败重启电脑可以重新到达漏洞点函数.

__kernel_entry NTSYSCALLAPI NTSTATUS NtQueryDirectoryFile(
  [in]           HANDLE                 FileHandle,
  [in, optional] HANDLE                 Event,
  [in, optional] PIO_APC_ROUTINE        ApcRoutine,
  [in, optional] PVOID                  ApcContext,
  [out]          PIO_STATUS_BLOCK       IoStatusBlock,
  // 用户模式直接与内核输出缓冲区进行映射=FileInformation
  [out]          PVOID                  FileInformation,
  [in]           ULONG                  Length,
  [in]           FILE_INFORMATION_CLASS FileInformationClass,
  [in]           BOOLEAN                ReturnSingleEntry,
  [in, optional] PUNICODE_STRING        FileName,
  [in]           BOOLEAN                RestartScan
);
__int64 __fastcall CscQueryDirectory(PRX_CONTEXT a1)
{
CscUpdateAndCaptureConnectionStateEx(pFcb, a1->pRelevantSrvOpen, (__int64)a1, 1u, (__int64)&ConnectionState, 1);
 if ( MrxSrvOpen
      && (((__int64)MrxSrvOpen->Key & 0x400) != 0 || *(_DWORD *)(*(_QWORD *)&devobj->SectorSize + 296LL))
      && (*(&devobj->AlignmentRequirement + 1) & 0x1000000) == 0
      && LODWORD(devobj->DeviceQueue.Lock)
      || *(_DWORD *)&devobj->DeviceQueue.Busy
      || *((_DWORD *)&devobj->DeviceQueue.1 + 1) )
    {
     
      ConnectionState|= 0x20;
    }
     if ( (ConnectionState & 0x20) == 0 )
   { goto err;
    }else{ 
      ConnectionStateref |= 0x10u;
    hr = CscQueryDirOnlineAndUpdateCache(a1, (__int64 *)&getctx, &ConnectionState, v59);HR
  }
}
__int64 __fastcall CscQueryDirOnlineAndUpdateCache(PRX_CONTEXT a1, __int64 *getctx, _BYTE *ConnectionState, __int64 a4)
{
int hr=mrxsmb!SmbShellQueryDirectory (a1);
if(sucessed(hr)){
hr=CscQueryDirStitchRemoteBuffer((__int64)pRelevantSrvOpen, getctx, v17);
}
__int64 __fastcall CscQueryDirStitchRemoteBuffer(__int64 a1, __int64 *a2, __int64 a3)
{ 
     //v8->high48.obufnowqword50 =// 用户模式直接与内核输出缓冲区进行映射
      outofboundaryval = (unsigned int *)v8->high48.obufnowqword50;
      v8->high48.obufselfqword58 = outofboundaryval;
      v8->high48.obufnowqword50 = (char *)outofboundaryval + *outofboundaryval;    
    obufnowqword50 = (_DWORD *)v8->high48.obufnowqword50;
    if ( *obufnowqword50 )
    {
      v13 = v9 - *obufnowqword50;
    }
    else
    {
      v8->high48.oplewtmpvalzerovulunsigned_int74 = v9;
    
      v8->high48.obuddupqword60 = obufnowqword50;
    }
    v8->high48.opusedrefdword70 = v13;
   return  hr = CscQueryDirStitchSingleEntry(a1, a2, (__int64)obufnowqword50, a3);
}
__int64 __fastcall CscQueryDirStitchSingleEntry(PMRX_SRV_OPEN a1, __int64 *a2, __int64 obuf, __int64 a4)
{
 UNICODE_STRING  v36.MaximumLength = *(_WORD *)(v12 + obufnowqword50);
  v36.Length = v36.MaximumLength;
  v36.Buffer = (PWSTR)(v7->high48.obufnowqword50 + (int)v7->high48.inclsfalg1dword78);
  UNICODE_STRING  v36=out of boundary kernel pool memory corruption//
  hr = CscQueryDirSearchForLocalName(a2, &v36, a4, (unsigned int **)&v38, (int **)&v37);
  hr == CscQueryDirOpenAndUpdateEntry(*(__int64 *)v41,v18, &v36.Length,  obuf,  (__int64)v15,   v17,   v25,   v43,   v42, &v35);
}

当控制流到达CscQueryDirOnlineAndUpdateCache了,会对PRX_CONTEXT上下文的虚标指针中调用mrxsmb!SmbShellQueryDirectory发起底层的文件目录查询操作,这个操作是个标准smb协议的QUERY_DIRECTORY调用,这就给poc一个稳定的条件触发用户态竞争条件TOCTOU窗口期篡改IRP缓冲区,可以先返回一个正常的协议回复报文,进入后面的处理代码,这里的v7->high48.obufnowqword50缓冲区指针与用户态NtQueryDirectoryFile参数FileInformation指针指向的是同一个地址指针.在这时候可以篡改IRP缓冲区数据导致的内存操作越界读写,也就是解引用后的outofboundaryval前2个字节UINT16的偏移量,csc驱动并没有对越界访问做出验证,在之后的CscQueryDirStitchSingleEntry会越界访问一个UNICODE_STRING结构,如果越界数据存在有效结构,会在CscQueryDirOpenAndUpdateEntry构造一个伪造的csc文件缓存文件对象entry结构体,或导致内核崩溃和可能的权限提升操作.以下是操作系统内核崩溃时bsod栈回溯结果和调试结果.

1: kd> !analyze -v
rax=0000000000000000 rbx=0000000000000000 rcx=ffffb400bf6fdb3e
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff802460aa59e rsp=fffff88c947e6880 rbp=0000000000000000
 r8=0000000000000006  r9=00000000000014c2 r10=fffff88c947e6bc0
r11=0000000000000a61 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei ng nz ac po cy
csc!CscStUtIsValidStoreEntryName+0x5e:
fffff802`460aa59e 410fb71409      movzx   edx,word ptr [r9+rcx] ds:ffffb400`bf6ff000=????
Resetting default scope
STACK_TEXT:  
fffff88c`947e5c48 fffff802`b13e72a2     : fffff88c`947e5cc8 00000000`00000001 00000000`00000080 fffff802`b1540601 : nt!DbgBreakPointWithStatus
fffff88c`947e5c50 fffff802`b13e6804     : 00000000`00000003 00000000`00000000 fffff802`b1540770 fffff88c`947e6370 : nt!KiBugCheckDebugBreak+0x12
fffff88c`947e5cb0 fffff802`b1333fb7     : ffffb400`bf6ff000 fffff802`b12eddc7 00000000`00000000 fffff88c`947e65c0 : nt!KeBugCheck2+0xc04
fffff88c`947e6440 fffff802`b11a6a66     : 00000000`00000050 ffffb400`bf6ff000 00000000`00000000 fffff88c`947e66f0 : nt!KeBugCheckEx+0x107
fffff88c`947e6480 fffff802`b11a47ea     : 00000000`00000001 00000000`00001000 ffffb400`bf6ff000 ffffca80`00000000 : nt!MiSystemFault+0x47e
fffff88c`947e6580 fffff802`b1535c41     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00007fff : nt!MmAccessFault+0x37a
fffff88c`947e66f0 fffff802`460aa59e     : 00000000`00000100 fffff802`b10e1f09 ffffdb00`768f3da0 fffff802`4610b3a4 : nt!KiPageFaultDispatchTrap+0x9b
fffff88c`947e6880 fffff802`4610b3a4     : 00000000`00000000 fffff88c`947e69a0 00000000`00102002 00000000`00000000 : csc!CscStUtIsValidStoreEntryName+0x5e
fffff88c`947e68a0 fffff802`460b0816     : fffff88c`947e6cf8 fffff802`460a4ad5 00000000`00000000 fffff88c`947e6cc0 : csc!CscEnpFindOrCreateEntryEx+0x2c4
fffff88c`947e6af0 fffff802`46118f93     : 00000000`00000000 ffffdb00`767e68d0 ffffdb00`6b5c60e0 00000000`80000006 : csc!CscEnFindOrCreateEntry+0x56
fffff88c`947e6b60 fffff802`460b179f     : ffffdb00`763bfe01 00000000`00000019 ffffdb00`768f3da0 fffff88c`947e6cf0 : csc!CscStorepFindOrCreateEntryEx+0x193
fffff88c`947e6c10 fffff802`4611306f     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : csc!CscStoreFindOrCreateEntry+0x4b
fffff88c`947e6c70 fffff802`461135af     : fffff88c`947e70b8 ffffa38c`509c96c0 ffffa38c`509c96c0 fffff88c`00000000 : csc!CscQueryDirOpenAndUpdateEntry+0x2bf
fffff88c`947e6dc0 fffff802`46112d49     : 00000000`00000000 ffffdb00`6b5be000 ffffa38c`509c94f0 ffffa38c`509c94f0 : csc!CscQueryDirStitchSingleEntry+0x28f
fffff88c`947e6f60 fffff802`461157fa     : 00000000`00000000 ffffa38c`509c94f0 ffffdb00`6b5be000 00000000`00000000 : csc!CscQueryDirStitchRemoteBuffer+0x81
fffff88c`947e6fb0 fffff802`46114c53     : ffffdb00`769202f8 ffffa38c`509c94f0 fffff88c`947e7148 ffffa38c`509c96c0 : csc!CscQueryDirOnlineAndUpdateCache+0x15a
fffff88c`947e7020 fffff802`4606bb62     : 00000000`00000000 ffffa38c`509c94f0 ffffb400`bf6fdae0 00000000`00000000 : csc!CscQueryDirectory+0x933
fffff88c`947e7190 fffff802`4606b69f     : ffffa38c`509c94f0 ffffa38c`365d0de0 ffffdb00`76920010 fffff802`00000003 : rdbss!RxQueryDirectory+0x342
fffff88c`947e7210 fffff802`46002508     : ffffa38c`365d0de0 00000000`00000000 ffffa38c`509c94f0 ffffa38c`530a4701 : rdbss!RxCommonDirectoryControl+0xbf
fffff88c`947e7270 fffff802`4606c4d4     : ffffa38c`365d0de0 00000000`00000000 00000000`00000000 fffff802`b10ec032 : rdbss!RxFsdCommonDispatch+0xa28
fffff88c`947e7480 fffff802`4802a522     : 00000000`00000000 ffffa38c`530ac7f0 ffffa38c`530ac788 ffffdb00`750a9b50 : rdbss!RxFsdDispatch+0x84
fffff88c`947e74d0 fffff802`b1006fbf     : 00000000`00000000 ffffa38c`530a4700 ffffdb00`595b7b10 ffffa38c`365d0f40 : mrxsmb!MRxSmbFsdDispatch+0xa2
fffff88c`947e7510 fffff802`b1006f33     : fffff802`454da010 ffffa38c`37bef8f0 ffffa38c`530ac740 ffffa38c`365d0f40 : nt!IopfCallDriver+0x5f
fffff88c`947e7550 fffff802`454ebfe8     : 00000000`00000000 ffffa38c`365d0de0 00000000`00000000 fffff802`b119a11b : nt!IofCallDriver+0x13
fffff88c`947e7580 fffff802`454ebba9     : ffffdb00`595b7b10 00000000`00000000 00000000`00000000 00000000`00000000 : mup!MupStateMachine+0x218
fffff88c`947e7600 fffff802`b1006fbf     : ffffa38c`37befb01 00000000`00000000 ffffa38c`530ac740 ffffa38c`37befb01 : mup!MupFsdIrpPassThrough+0xd9
fffff88c`947e7670 fffff802`b1006f33     : fffff88c`947e7798 fffff802`42e49f00 00000000`00000003 00000000`000000c0 : nt!IopfCallDriver+0x5f
fffff88c`947e76b0 fffff802`42e47421     : 00000000`00000000 ffffa38c`365d0f88 ffffa38c`365d0de0 00000000`00000000 : nt!IofCallDriver+0x13
fffff88c`947e76e0 fffff802`42e445ef     : ffffa38c`365d0f88 ffffa38c`00000000 fffff88c`80000000 fffff88c`947e1000 : FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x191
fffff88c`947e7780 fffff802`b1006fbf     : ffffa38c`3fa2c7e0 ffffa38c`3fa2c7e0 ffffa38c`4f9ae940 00000000`00000000 : FLTMGR!FltpDispatch+0xaf
fffff88c`947e77e0 fffff802`b1006f33     : fffff88c`947e79d1 fffff802`b100dfd3 00000000`00000004 00000000`00000004 : nt!IopfCallDriver+0x5f
fffff88c`947e7820 fffff802`b1006d09     : fffff88c`947e7a40 fffff802`b1781996 00000000`00000001 ffffa38c`3fa2c7e0 : nt!IofCallDriver+0x13
fffff88c`947e7850 fffff802`b17820fc     : ffffa38c`3fa2c7e0 00000000`00000000 ffffa38c`365d0de0 00007ffb`a0702000 : nt!IopCallDriverReference+0xe9
fffff88c`947e78d0 fffff802`b1781509     : 00000000`00000a44 ffffcabf`00000000 ffffa38c`3fa2c7e0 00000000`00000001 : nt!IopSynchronousServiceTail+0x268
fffff88c`947e7950 fffff802`b153a3c5     : ffffa38c`364cb080 00000000`0000000a 00000000`00000000 00000000`00000000 : nt!NtQueryDirectoryFile+0xe9
fffff88c`947e7a00 00007ffc`23860194     : 00007ffb`a0685976 00000004`00000000 0000009b`85d8eba0 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25
0000009b`85d8eb38 00007ffb`a0685976     : 00000004`00000000 0000009b`85d8eba0 00000000`00000000 00007ffb`a0068cf1 : ntdll!NtQueryDirectoryFile+0x14
//调试结果
15: kd> !thread
THREAD ffffae0b308b2080  Cid 2bc4.3220  Teb: 0000008000321000 Win32Thread: 0000000000000000 RUNNING on processor f
IRP List:
    ffffae0b31c44010: (0006,04c0) Flags: 00060800  Mdl: ffffae0b27f14790

15: kd> dt nt!_irp  ffffae0b31c44010
   +0x000 Type             : 0n6
   +0x002 Size             : 0x4c0
   +0x004 AllocationProcessorNumber : 6
   +0x006 Reserved1        : 0
   +0x008 MdlAddress       : 0xffffae0b`27f14790 _MDL
   +0x010 Flags            : 0x60800
   +0x014 Reserved2        : 0
   +0x018 AssociatedIrp    : &lt;unnamed-tag&gt;
   +0x020 ThreadListEntry  : _LIST_ENTRY [ 0xffffae0b`308b25c0 - 0xffffae0b`308b25c0 ]
   +0x030 IoStatus         : _IO_STATUS_BLOCK
   +0x048 UserIosb         : 0x000000c0`9c5c0b60 _IO_STATUS_BLOCK
   +0x048 IoRingContext    : 0x000000c0`9c5c0b60 Void
   +0x050 UserEvent        : 0xffffae0b`302c04e0 _KEVENT
   +0x058 Overlay          : &lt;unnamed-tag&gt;
   +0x068 CancelRoutine    : 0xfffff807`6b601760     void  rdbss!RxCancelRoutine+0
   //user mode output buffer is mapped directly to kernel irp mdl buffer
   +0x070 UserBuffer       : 0x000000c0`9704
 15: kd> dx -id 0,0,ffffae0b30ff00c0 -r1 ((ntkrnlmp!_MDL *)0xffffae0b27f14790)
((ntkrnlmp!_MDL *)0xffffae0b27f14790)                 : 0xffffae0b27f14790 [Type: _MDL *]
    [+0x000] Next             : 0x0 [Type: _MDL *]
    [+0x008] Size             : 64 [Type: short]
    [+0x00a] MdlFlags         : 395 [Type: short]
    [+0x00c] AllocationProcessorNumber : 0x6 [Type: unsigned short]
    [+0x00e] Reserved         : 0x0 [Type: unsigned short]
    [+0x010] Process          : 0xffffae0b30ff00c0 [Type: _EPROCESS *]
    //用户模式输出缓冲区被直接映射到内核 IRP MDL 缓冲区
    [+0x018] MappedSystemVa   : 0xffffcf81d53fb6a0 [Type: void *]
    [+0x020] StartVa          : 0xc097045000 [Type: void *]
    [+0x028] ByteCount        : 0x1000 [Type: unsigned long]
    [+0x02c] ByteOffset       : 0x6a0 [Type: unsigned long]  
15: kd> dq 0xffffcf81d53fb6a0 
//越界解引用
ffffcf81`d53fb6a0  ffffffff`ffffffff ffffffff`ffffffff
ffffcf81`d53fb6b0  ffffffff`ffffffff ffffffff`ffffffff

CVE-2026-26176漏洞补丁对比

__int64 __fastcall CscQueryDirectory(__int64 a1)
{
  if ( (unsigned int)Feature_3204389179__private_IsEnabledDeviceUsageNoInline() )
    {
      Pool2 = ExAllocatePool2(64, len, 1917088579);    
      *(_QWORD *)(a1 + 0x1B8) = Pool2;
    }
    QueryDirEnumSet((__int64 *)(v7 + 72), *(_DWORD *)(a1 + 0x1B0), *(_QWORD *)(a1 + 0x1B8), v4, 0);
    hr = CscQueryDirOnlineAndUpdateCache(a1, &v35, (__int64)&v44, v31);	
 if ( (unsigned int)Feature_3204389179__private_IsEnabledDeviceUsageNoInline() && v27 )
    {
      RtlCopyVolatileMemory(irpbuf, (a1 + 0x1B8), len);
   
    }	
}	

应用补丁后IRP缓冲区被保存到了一个临时的缓冲区指针中,用户态即使获得了TOCTOU竞争条件,对这个缓冲区修改也不会影响临时保存的数据内容,在NtQueryDirectoryFile数据处理完成后再把临时的数据写回这个原缓冲区,这样就不存在竞争条件篡改数据的可能性,微软采用这种方式修复漏洞.

结论

本文分析了客户端缓存文件系统驱动程序(csc.sys)特权提升漏洞CVE-2026-26176重现了篡改IRP缓冲区相关文件操作导致操作系统内核崩溃bsod或特权提升的利用过程.

漏洞复现

笔者漏洞poc采用.net程序复现,出于安全原因笔者不能提供完整的poc代码,下图是笔者在的Win11 26h2 wip上成功复现了CVE的利用效果

相关引用

Smb Quic重放工具

Smb Quic重放工具项目

CVE-2026-26176致谢

参与贡献

作者来自ZheJiang Guoli Security Technology,邮箱cbwang505@hotmail.com


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回