您现在的位置: 主页 > 资讯 > intel英特尔&微软Microsoft > 微软WindowsFastFAT.sysFAT分区拒绝服务漏洞重现
本文所属标签:
为本文创立个标签吧:

微软WindowsFastFAT.sysFAT分区拒绝服务漏洞重现

来源:windows 网络用户发布,如有版权联系网管删除 2018-08-30 

  还记得去年的 MS14-063 FAT32驱动内核溢出漏洞么?今天出续集了,但是这一次是在FAT12分区。 

  演示视频

  分析

  - 受影响系统

  从Windows NT到Windows 7 SP1

  - 我测试的机型

* Windows XP SP3 x86 
* Windows 7 SP1 x86/x64

  BUG重现:创建FAT12分区并在0 16(Sectors per FAT)设置一个WORD,例如0 3000 

  注意:值不要超过0x3FFF 

  查阅Loopback Device资料建议,并且建议设置参数bs=512 count=32067 

  镜像可为空

  细节:在FAT12引导扇区中“Sectors per FAT”字段中的值发生错误,导致在FAT1分区映射到缓存期间尝试读取未分配的内存区域。 

  错误的分区显示如下:

SosoImg

  崩溃

  Windows 7 SP1 x86

kd> !analyze -v 
******************************************************************************* 
*                                                                             * 
*                        Bugcheck Analysis                                    * 
*                                                                             * 
******************************************************************************* 
PAGE_FAULT_IN_NONPAGED_AREA (50) 
Invalid system memory was referenced.  This cannot be protected by try-except, 
it must be protected by a Probe.  Typically the address is just plain bad or it 
is pointing at freed memory. 
Arguments: 
Arg1: a3f00000, memory referenced. 
Arg2: 00000000, value 0 = read operation, 1 = write operation. 
Arg3: 82a6a05e, If non-zero, the instruction address which referenced the bad memory 
  address.
Arg4: 00000000, (reserved) 
Debugging Details: 
------------------ 
READ_ADDRESS:  a3f00000 
FAULTING_IP: 
nt!CcMapData+ae 
82a6a05e 8a0e            mov     cl,byte ptr [esi] 
MM_INTERNAL_CODE:  0 
DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT 
BUGCHECK_STR:  0x50 
PROCESS_NAME:  explorer.exe 
CURRENT_IRQL:  2 
TRAP_FRAME:  a2447414 -- (.trap 0xffffffffa2447414) 
ErrCode = 00000000 
eax=000006e2 ebx=86eb8b98 ecx=a2447400 edx=00000011 esi=a3f00000 edi=0000000f 
eip=82a6a05e esp=a2447488 ebp=a24474c8 iopl=0         nv up ei pl nz ac po nc 
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010212 
nt!CcMapData+0xae: 
82a6a05e 8a0e            mov     cl,byte ptr [esi]          ds:0023:a3f00000=?? 
Resetting default scope 
LAST_CONTROL_TRANSFER:  from 82916d5f to 828b27b8 
STACK_TEXT:  
a2446f64 82916d5f 00000003 6641e18b 00000065 nt!RtlpBreakWithStatusInstruction 
a2446fb4 8291785d 00000003 00000000 00082982 nt!KiBugCheckDebugBreak+0x1c 
a2447378 828c5879 00000050 a3f00000 00000000 nt!KeBugCheck2+0x68b 
a24473fc 82878aa8 00000000 a3f00000 00000000 nt!MmAccessFault+0x104 
a24473fc 82a6a05e 00000000 a3f00000 00000000 nt!KiTrap0E+0xdc 
a24474c8 975dbb32 86e819c0 004474ec 00721e00 nt!CcMapData+0xae 
a24474f4 975d9e1d a2b52fb8 85dad920 00001000 fastfat!FatReadVolumeFile+0x3a 
a2447580 975da534 a2b52fb8 a2447524 00000002 fastfat!FatExamineFatEntries+0x11f 
a24475e8 975ecd64 a2b52fb8 85dad920 3519a638 fastfat!FatSetupAllocationSupport+0x38a 
a2447774 975ee3cf a2b52fb8 8a9b0da8 a3392fa8 fastfat!FatMountVolume+0x418 
a2447794 975ee478 a2b52fb8 93528e90 3519a6ac fastfat!FatCommonFileSystemControl+0x3f 
a24477e0 82b696c3 82275620 93528e90 93528e90 fastfat!FatFsdFileSystemControl+0x82 
a2447804 8286ebd5 00000001 93528ff4 82275620 nt!IovCallDriver+0x258 
a2447818 85499a56 270d61d5 8229bde8 93528e90 nt!IofCallDriver+0x1b 
a2447878 85499c5b 8229bde8 93528e90 86f2c678 fltmgr!FltpFsControlMountVolume+0x180 
a24478a8 82b696c3 8229bde8 93528e90 93528e90 fltmgr!FltpFsControl+0x5b 
a24478cc 8286ebd5 00000001 8296fb88 8229bde8 nt!IovCallDriver+0x258 
a24478e0 829d1dd9 82804870 8a9b0da8 82804900 nt!IofCallDriver+0x1b 
a2447944 828df92e 8a9b0da8 85dac000 00000000 nt!IopMountVolume+0x1d8 
a244797c 82a7ddfb 85dac008 a2447aa8 a2447a40 nt!IopCheckVpbMounted+0x64 
a2447a60 82a5dd1e 8a9b0da8 851cfde8 85d66750 nt!IopParseDevice+0x7db 
a2447adc 82a6e147 00000000 a2447b30 00000040 nt!ObpLookupObjectName+0x4fa 
a2447b38 82a64c25 02effc44 851cfde8 828b1d01 nt!ObOpenObjectByName+0x165 
a2447bb4 82a884a4 02effca0 00100081 02effc44 nt!IopCreateFile+0x673 
a2447c00 828758c6 02effca0 00100081 02effc44 nt!NtCreateFile+0x34 
a2447c00 776170f4 02effca0 00100081 02effc44 nt!KiSystemServicePostCall 
02effc00 77615614 7573a9d9 02effca0 00100081 ntdll!KiFastSystemCallRet 
02effc04 7573a9d9 02effca0 00100081 02effc44 ntdll!ZwCreateFile+0xc 
02effca8 772ce99f 00004000 00100081 00000007 KERNELBASE!CreateFileW+0x35e 
02effcd4 761a2fc5 03cc0038 00000001 00000007 kernel32!CreateFileWImplementation+0x69 
02effd38 761a2bc9 03cc0038 00000001 00000000 SHELL32!CLocalInterruptSource::v_CreateEvent+0x41 
02effd5c 761aac0f 0368f598 00000000 02effd94 SHELL32!CFSInterruptSource::GetEvent+0x7b 
02effd9c 761aa92a 02effdc0 00000000 006e7a90 SHELL32!CChangeNotify::_GetInterruptEvents+0x93 
02effdc8 7611561b 00000000 00000000 00000067 SHELL32!CChangeNotify::_MessagePump+0x67 
02effde0 75fd43c0 006e7a90 00000000 00000000 SHELL32!CChangeNotify::s_ThreadProc+0x4f 
02effe68 772cee1c 0201ed74 02effeb4 776337eb SHLWAPI!WrapperThreadProc+0x1b5 
02effe74 776337eb 0201ed74 758640f9 00000000 kernel32!BaseThreadInitThunk+0xe 
02effeb4 776337be 75fd42ed 0201ed74 00000000 ntdll!__RtlUserThreadStart+0x70 
02effecc 00000000 75fd42ed 0201ed74 00000000 ntdll!_RtlUserThreadStart+0x1b 
STACK_COMMAND:  kb 
FOLLOWUP_IP: 
nt!CcMapData+ae 
82a6a05e 8a0e            mov     cl,byte ptr [esi] 
SYMBOL_STACK_INDEX:  5 
SYMBOL_NAME:  nt!CcMapData+ae 
FOLLOWUP_NAME:  MachineOwner 
MODULE_NAME: nt 
IMAGE_NAME:  ntkrpamp.exe 
DEBUG_FLR_IMAGE_TIMESTAMP:  521e9cb6 
FAILURE_BUCKET_ID:  0x50_VRF_nt!CcMapData+ae 
BUCKET_ID:  0x50_VRF_nt!CcMapData+ae 
Followup: MachineOwner 
---------

  漏洞代码:

  wrk-v1.2basentoscachepinsup.c

Line 72: 
BOOLEAN 
CcMapData ( 
  __in PFILE_OBJECT FileObject,
  __in PLARGE_INTEGER FileOffset,
  __in ULONG Length,
  __in ULONG Flags,
  __out PVOID *Bcb,
  __deref_out_bcount(Length) PVOID *Buffer
  )
... 
Line 155: 
  ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES((ULongToPtr(FileOffset->LowPart)), Length);
  PETHREAD Thread = PsGetCurrentThread();
  BOOLEAN ReturnStatus;
  DebugTrace(+1, me, "CcMapDatan", 0 );
  MmSavePageFaultReadAhead( Thread, &SavedState );
  ReturnStatus = CcMapDataCommon( FileObject,
  FileOffset,
  Length,
  Flags,
  &TempBcb,
  Buffer );
... 
Line 193 
  //
  //  Loop to touch each page
  //
  BaseAddress = *Buffer;
  while (PageCount != 0) {
  MmSetPageFaultReadAhead( Thread, PageCount - 1 );
  ch = *((volatile UCHAR *)(BaseAddress));   // <----------   CRASH!!!!
  BaseAddress = (PCHAR) BaseAddress + PAGE_SIZE;
  PageCount -= 1;
  }

  PageCount基于控制长度值进行计算,在这种情况下(读取FATx)包括:

  Sectors per FAT * Bytes per sector

kd> . frame /c 5 
kd> dd ebp+10 L1 //get Length value 
f53e1510  00721e00 
kd> ?00721e00 / 0x200(= Bytes per sector) 
Evaluate expression: 14607 = 0000390f (= Sectors per FAT)

  FileOffset也就等于:

kd> dt _LARGE_INTEGER poi(ebp+c) 
nt!_LARGE_INTEGER 
  0x200
  +0x000 LowPart          : 0x200
  +0x004 HighPart         : 0
  +0x000 u                : __unnamed
  +0x000 QuadPart         : 512

  调用PageCount计算的这些值:

Evaluate expression: 1826 = 00000722

  while迭代循环,通过PAGE_SIZE增加BaseAddress指针。所以在这种情况下内存区域会被“覆盖”:

kd> ?(0x722 * 0x1000) / 0x400 
------------^-----------^----------^---- 
PageCount     PAGE_SIZE     1KB 
Evaluate expression: 7304 = 00001c88 
kd> ?00001c88 / 0x400 
Evaluate expression: 7 = 00000007   ~   7MB

  接下来检测一下我们能够缓存多少字节:

  wrk-v1.2basentoscachepinsup.c

Line 241: 
BOOLEAN 
CcMapDataCommon ( 
  IN PFILE_OBJECT FileObject,
  IN PLARGE_INTEGER FileOffset,
  IN ULONG Length,
  IN ULONG Flags,
  OUT PVOID *Bcb,
  OUT PVOID *Buffer
  )
... 
Line 350: 
  //
  //  Get pointer to SharedCacheMap.
  //
  SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
  //
  //  Call local routine to Map or Access the file data.  If we cannot map
  //  the data because of a Wait condition, return FALSE.
  //
  if (FlagOn(Flags, MAP_WAIT)) {
  *Buffer = CcGetVirtualAddress( SharedCacheMap,
  *FileOffset,
  (PVACB *)&TempBcb,
  &ReceivedLength );
  ASSERT( ReceivedLength >= Length ); // maybe convert it to IF ?
  }

  在CcGetVirtualAddress中检测ReceiveLength:

  wrk-v1.2basentoscachevacbsup.c

Line 388: 
ULONG VacbOffset = FileOffset.LowPart & (VACB_MAPPING_GRANULARITY - 1); 
... 
Line  449: 
*ReceivedLength = VACB_MAPPING_GRANULARITY - VacbOffset;

  VACB_MAPPING_GRANULARITY的值是多少?

  wrk-v1.2basentosinccache.h

Line 31: 
#define VACB_MAPPING_GRANULARITY         (0x40000)

  从上面的代码片段中获知ReceiveLength应该是大于等于0 40000 bytes也就是256KB.

  MSDN CcMapData

  微软官方CcMapData文档[点我] 

  在缓存管理器中CcMapData无法通过视图边界映射数据,系统缓存管理器中的文件标准大小为256 KB(缓存管理器的视图的大小是通过系统定义常数VACB_MAPPING_GRANULARITY指定的,其大小在ntifs.h中设置为256 KB),映射区域不能超越256 KB。因此最大映射区域为256 KB,从文件中的偏移量从256 KB开始。

  代码和文档都清晰的指出映射文件数据不能超过256 KB,在我们这个例子中内核大于有7M可用空间,迭代这个超过256 KB会导致崩溃。 

  为何存在这个BUG

  长度值缺少验证,会导致这个迭代无限循环

  wrk-v1.2basentoscachepinsup.c

Line 198 
  while (PageCount != 0) {
  MmSetPageFaultReadAhead( Thread, PageCount - 1 );
  ch = *((volatile UCHAR *)(BaseAddress));   // <----------   CRASH!!!!
  BaseAddress = (PCHAR) BaseAddress + PAGE_SIZE;
  PageCount -= 1;
  }

  超过可用映射/分配区域

  并非每次都触发

  在实验中我发现不是每一个Sectors per FAT的值都会超过0 0200从而导致崩溃,例如Sectors per FAT设置为0 4000就是一个例外!FatCommonRead:

  堆栈跟踪:Sectors per FAT == 40 00

Windows XP SP3 
ChildEBP RetAddr  Args to Child              
bad46fc0 b7e0d505 86a69e50 bad46fec 804e24f1 Fastfat!FatExceptionFilter+0x5 
bad46fcc 804e24f1 bad46ff4 00000000 bad46ff4 Fastfat!FatFsdRead+0x12b 
bad46ff4 804db49a bad470d8 bad47518 bad47128 nt!_except_handler3+0x61 
bad47018 804db46b bad470d8 bad47518 bad47128 nt!ExecuteHandler2+0x26 
bad470c8 804dc6a1 bad470d8 bad47128 c000000d nt!ExecuteHandler+0x24 
bad473fc b7e12fc4 c000000d 86a69e50 8667b888 nt!ExRaiseStatus+0xb5 
bad474b8 b7e0d69a 86a69e50 8667b888 86a501e8 Fastfat!FatCommonRead+0x66b 
bad47528 804e37f7 8686ba98 8667b888 00000000 Fastfat!FatFsdRead+0x13d 
bad47538 804f95d8 00000000 86b01ad0 86b01ae0 nt!IopfCallDriver+0x31 
bad4754c 804f95ff 8686ba98 86b01b08 86b01ae8 nt!IopPageReadInternal+0xf4 
bad4756c 804f9264 86a501e8 86b01b08 86b01ae8 nt!IoPageRead+0x1b 
bad475e0 804eba6a 0dead8c0 c7fc0000 c031ff00 nt!MiDispatchFault+0x274 
bad47630 804e1718 00000000 c7fc0000 00000000 nt!MmAccessFault+0x5bc 
bad47630 8056d716 00000000 c7fc0000 00000000 nt!KiTrap0E+0xcc 
bad47708 b7e15b25 86a501e8 bad47734 00001000 nt!CcMapData+0xef 
bad4773c b7e1e8b6 86a84e28 8698b3a8 00000000 Fastfat!FatReadDirectoryFile+0x92 
bad47770 b7e137b7 86a84e28 8686bb90 bad47880 Fastfat!FatLocateVolumeLabel+0x7f 
bad4790c b7e10a93 86a84e28 86b6a718 86bd3af0 Fastfat!FatMountVolume+0x49b 
bad4792c b7e10a38 86a84e28 8690eaf0 8690ec78 Fastfat!FatCommonFileSystemControl+0x49 
bad47978 804e37f7 86a2d928 8690eaf0 8690ec9c Fastfat!FatFsdFileSystemControl+0x85 
EXCEPTION: 
Fastfat!FatExceptionFilter+0x5: 
b7e0d485 53              push    ebx 
kd> .exr poi(poi(ebp+c)) 
ExceptionAddress: b7e12fc4 (Fastfat!FatCommonRead+0x0000066b) 
  ExceptionCode: c000000d  // STATUS_INVALID_PARAMETER
  ExceptionFlags: 00000001
NumberParameters: 0

  我并没有深入下去,当然也就无法指出在代码中哪个地方导致的这个例外。所以我猜测可能是已经存在一个长度验证,但是精准度还不够!

  * 参考来源:Icewall,编译/FB小编鸢尾,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM) 




              查看评论 回复



嵌入式交流网主页 > 资讯 > intel英特尔&微软Microsoft > 微软WindowsFastFAT.sysFAT分区拒绝服务漏洞重现
 缓存 这个 映射

"微软WindowsFastFAT.sysFAT分区拒绝服务漏洞重现"的相关文章

网站地图

围观()