Win7下插U盘引发的溢出漏洞类安全问题

看了"Introducing the USB Stick of Death",真是有些意外。Win7下的ntfs.sys中竟然有这样一个隐患。下面就是对该文部分内容的大致翻译。

这个bug是由Gynvael Coldwind发现的,并由Mateusz “j00ru” Jurczyk折腾出了利用这个溢出漏洞来提权的操作。

这个安全问题是他们在几个月前检查各设备驱动的安全性和健壮性时发现的,他们的研究重点是NTFS相关的驱动,因为这货异常复杂和庞大,他们认为肯定有一些漏洞还没被发现,而且相关的一些设备驱动程序肯定有一些不用太费劲就可以找到的问题,结果是他们成功了。

当简单的进行插入U盘的操作时,操作系统会自动加载它并会触发一个ntfs.sys中的漏洞。

他们发现了一些可能会被利用的问题,其中一个有趣的问题,虽然并不是太严重,但可以用来本地提权。估计木马编写者们应该很喜欢这样的漏洞。

他们首先是试图找一些能重现的问题,结果在大约17个小时的尝试中,找到了一个可以重复出现的让win7 蓝屏的操作。

结果类似这样:

EXCEPTION_RECORD:  fffff88006fd7fd8 -- (.exr 0xfffff88006fd7fd8)
ExceptionAddress: fffff8800125311e (Ntfs!NtfsAcquirePagingResourceExclusive+0x0000000000000016)
  ExceptionCode: c0000005 (Access violation)
 ExceptionFlags: 00000000
NumberParameters: 2
  Parameter[0]: 0000000000000000
  Parameter[1]: 0000000000000060
Attempt to read from address 0000000000000060

CONTEXT:  fffff88006fd7830 -- (.cxr 0xfffff88006fd7830)
rax=0000000000000702 rbx=fffffa8005c0b180 rcx=0000000000000000
rdx=fffff8a005859ce0 rsi=fffffa8005c0b7e0 rdi=0000000000000000
rip=fffff8800125311e rsp=fffff88006fd8218 rbp=fffff88006fd85a0
r8=0000000000000001  r9=0000000000000000 r10=fffff8a00b254010
r11=fffff88006fd81e8 r12=fffffa8005b36ae0 r13=0000000000000000
r14=0000000000000001 r15=00000000c000026e
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
Ntfs!NtfsAcquirePagingResourceExclusive+0x16:
fffff880`0125311e 488b4960        mov     rcx,qword ptr [rcx+60h] ds:002b:00000000`00000060=????????????????
Resetting default scope

[...]

STACK_TEXT: 
fffff880`06fd8218 fffff880`01326de4 : [...] : Ntfs!NtfsAcquirePagingResourceExclusive+0x16
fffff880`06fd8220 fffff880`013178a3 : [...] : Ntfs!NtfsPerformDismountOnVcb+0x758
fffff880`06fd8330 fffff880`01317656 : [...] : Ntfs!NtfsLockVolumeInternal+0xf3
fffff880`06fd83a0 fffff880`013053ee : [...] : Ntfs!NtfsLockVolume+0x1f6
fffff880`06fd8480 fffff880`0130553d : [...] : Ntfs!NtfsUserFsRequest+0x2de
fffff880`06fd84c0 fffff880`0102ebcf : [...] : Ntfs!NtfsFsdFileSystemControl+0x13d
fffff880`06fd8560 fffff880`01031aea : [...] : fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x24f
fffff880`06fd85f0 fffff880`010670b5 : [...] : fltmgr!FltPerformSynchronousIo+0x2ca
fffff880`06fd8690 fffff880`01067b38 : [...] : fltmgr!IssueControlOperation+0x395
fffff880`06fd8720 fffff880`031555df : [...] : fltmgr!FltFsControlFile+0x48
fffff880`06fd8780 fffff880`03155d0e : [...] : FsDepends!DepFSSendDismountRequest+0x143
fffff880`06fd87e0 fffff880`0315582d : [...] : FsDepends!DepFSDismountDependencyList+0xd6
fffff880`06fd8840 fffff880`031747a8 : [...] : FsDepends!DependentFSDismountForUnsurface+0x175
fffff880`06fd88a0 fffff880`031749f2 : [...] : vhdmp!VhdmpiHaltActiveSurface+0x78
fffff880`06fd88f0 fffff880`03177156 : [...] : vhdmp!VhdmpiHaltSurfaceOrWait+0xb2
fffff880`06fd8940 fffff880`0316e117 : [...] : vhdmp!VhdmpiRemoveVirtualDisk+0x246
fffff880`06fd8990 fffff880`03166177 : [...] : vhdmp! ?? : [...] :FNODOBFM: [...] :`string'+0x4d87
fffff880`06fd89c0 fffff800`0299e717 : [...] : vhdmp!VhdmpFirstLevelIrpHandler+0x87
fffff880`06fd8a10 fffff800`0299ef76 : [...] : nt!IopXxxControlFile+0x607
fffff880`06fd8b40 fffff800`02687453 : [...] : nt!NtDeviceIoControlFile+0x56
fffff880`06fd8bb0 00000000`76e0138a : [...] : nt!KiSystemServiceCopyEnd+0x13
00000000`010fe548 000007fe`fd49a249 : [...] : ntdll!NtDeviceIoControlFile+0xa
00000000`010fe550 00000000`76ca683f : [...] : KERNELBASE!DeviceIoControl+0x75
00000000`010fe5c0 000007fe`f32d3994 : [...] : kernel32!DeviceIoControlImplementation+0x7f
00000000`010fe610 000007fe`f2c6886b : [...] : VirtDisk!DetachVirtualDisk+0x6c
00000000`010fe670 00000000`ff61f734 : [...] : vdsvd!COpenVDisk: [...] :Detach+0xb3
00000000`010fe6a0 000007fe`fd8823d5 : [...] : vds!CVdsOpenVDisk: [...] :Detach+0x3c
00000000`010fe6e0 000007fe`fd92b68e : [...] : RPCRT4!Invoke+0x65
00000000`010fe740 000007fe`fd8848d6 : [...] : RPCRT4!Ndr64StubWorker+0x61b
00000000`010fed00 000007fe`fee60883 : [...] : RPCRT4!NdrStubCall3+0xb5
00000000`010fed60 000007fe`fee60ccd : [...] : ole32!CStdStubBuffer_Invoke+0x5b [d:\w7rtm\com\rpc\ndrole\stub.cxx @ 1586]
00000000`010fed90 000007fe`fee60c43 : [...] : ole32!SyncStubInvoke+0x5d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1187]
00000000`010fee00 000007fe`fed1a4f0 : [...] : ole32!StubInvoke+0xdb [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1396]
00000000`010feeb0 000007fe`fee614d6 : [...] : ole32!CCtxComChnl: [...] :ContextInvoke+0x190 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 1262]
00000000`010ff040 000007fe`fee6122b : [...] : ole32!AppInvoke+0xc2 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1086]
00000000`010ff0b0 000007fe`fee5fd6d : [...] : ole32!ComInvokeWithLockAndIPID+0x52b [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 1727]
00000000`010ff240 000007fe`fd8750f4 : [...] : ole32!ThreadInvoke+0x30d [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4751]
00000000`010ff2e0 000007fe`fd874f56 : [...] : RPCRT4!DispatchToStubInCNoAvrf+0x14
00000000`010ff310 000007fe`fd87775b : [...] : RPCRT4!RPC_INTERFACE: [...] :DispatchToStubWorker+0x146
00000000`010ff430 000007fe`fd87769b : [...] : RPCRT4!RPC_INTERFACE: [...] :DispatchToStub+0x9b
00000000`010ff470 000007fe`fd877632 : [...] : RPCRT4!RPC_INTERFACE: [...] :DispatchToStubWithObject+0x5b
00000000`010ff4f0 000007fe`fd87532d : [...] : RPCRT4!LRPC_SCALL: [...] :DispatchRequest+0x422
00000000`010ff5d0 000007fe`fd892e7f : [...] : RPCRT4!LRPC_SCALL: [...] :HandleRequest+0x20d
00000000`010ff700 000007fe`fd892a35 : [...] : RPCRT4!LRPC_ADDRESS: [...] :ProcessIO+0x3bf
00000000`010ff840 00000000`76dcb68b : [...] : RPCRT4!LrpcIoComplete+0xa5
00000000`010ff8d0 00000000`76dcfeff : [...] : ntdll!TppAlpcpExecuteCallback+0x26b
00000000`010ff960 00000000`76ca652d : [...] : ntdll!TppWorkerThread+0x3f8
00000000`010ffc60 00000000`76ddc521 : [...] : kernel32!BaseThreadInitThunk+0xd
00000000`010ffc90 00000000`00000000 : [...] : ntdll!RtlUserThreadStart+0x1d

当卸载一个设备时,vps.exe发一个FSCTLLOCKVOLUME控制码给这个卷,然后处理代码就会触发一个空指针操作的崩溃异常。如果是我们写的代码也发一个这样的控制码,同样会触发这个问题。

触发这个崩溃异常处的代码反汇编后如下:

.text:0000000000019108 NtfsAcquirePagingResourceExclusive proc near
.text:0000000000019108
.text:0000000000019108                 mov     eax, 702h
.text:000000000001910D                 cmp     ax, [rdx]
.text:0000000000019110                 jz      short loc_1912C
.text:0000000000019112                 xor     ecx, ecx
.text:0000000000019114                 cmp     [rdx+10h], rcx
.text:0000000000019118                 jz      short loc_1911E
.text:000000000001911A                 mov     rcx, [rdx+70h]
.text:000000000001911E
.text:000000000001911E loc_1911E:
.text:000000000001911E                 mov     rcx, [rcx+60h]
.text:0000000000019122                 mov     dl, r8b
.text:0000000000019125                 jmp     cs:__imp_ExAcquireResourceExclusiveLite
.text:000000000001912C
.text:000000000001912C loc_1912C:
.text:000000000001912C                 mov     rcx, rdx
.text:000000000001912F                 jmp     short loc_1911E
.text:000000000001912F NtfsAcquirePagingResourceExclusive endp

C语言的伪码如下:

BOOLEAN NtfsAcquirePagingResourceExclusive(PSCB scb, BOOLEAN arg)
{
  PUNKNOWN_STRUCT ptr = NULL;

  if (scb->NodeTypeCode == 0x702) {
    ptr = scb;
  } else {
    if ( scb->PagingIoResource != NULL ) {
      ptr = scb->fcb;
    }
  }

  return ExAcquireResourceExclusiveLite(ptr->Resource, arg);
}

显然,问题就在这里,局部变量(在堆栈中)ptr被初始化为NULL,如果第一个if语句条件和第二个if语句条件都不满足的话,执行返回语句时就出事了:

  return ExAcquireResourceExclusiveLite(ptr->Resource, arg);

这里的ptr为NULL......

后面就是如何利用这个漏洞来获取系统控制权的步骤了。

标签: win7, 漏洞, usb stick, u盘, 溢出, 提权

添加新评论