Microsoft Windows FastFAT.sys FAT partition denial of service vulnerability reproduce-bug warning-the black bar safety net

2015-11-17T00:00:00
ID MYHACK58:62201569090
Type myhack58
Reporter 佚名
Modified 2015-11-17T00:00:00

Description

Remember last year's*MS14-0 6 3* FAT32 drive kernel overflow vulnerability? Today the sequel, but this one is in the FAT12 partition.

Analysis - The affected system From Windows NT to Windows 7 SP1 - I test models Windows XP SP3 x86 Windows 7 SP1 x86/x64 BUG reproduction: create a FAT12 partition and 0×1 6(Sectors per FAT)set a WORD, for example 0×3 0 0 0 Note: value not to exceed 0x3FFF Check the Loopback Device information, advice, and recommendations to set the parameters bs=5 1 2 count=3 2 0 6 7 The mirror can be empty Details: the FAT12 boot sector“Sectors per FAT”value in the field an error occurs, resulting in FAT1 partition is mapped to the cache during an attempt to read Unallocated memory area. The error of the partition is displayed as follows: ! Crash Windows 7 SP1 x86 kd> ! analyze-v


  • Bugcheck Analysis *

PAGE_FAULT_IN_NONPAGED_AREA (5 0) 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: 0 0 0 0 0 0 0 0, value 0 = read operation, 1 = write operation. Arg3: 82a6a05e, If non-zero, the instruction address which referenced the bad memory address. Arg4: 0 0 0 0 0 0 0 0, (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 = 0 0 0 0 0 0 0 0 eax=000006e2 ebx=86eb8b98 ecx=a2447400 edx=0 0 0 0 0 0 1 1 esi=a3f00000 edi=0000000f eip=82a6a05e esp=a2447488 ebp=a24474c8 iopl=0 nv up ei pl nz ac po nc cs=0 0 0 8 ss=0 0 1 0 ds=0 0 2 3 es=0 0 2 3 fs=0 0 3 0 gs=0 0 0 0 efl=0 0 0 1 0 2 1 2 nt! CcMapData+0xae: 82a6a05e 8a0e mov cl,byte ptr [esi] ds:0 0 2 3:a3f00000=?? Resetting default scope

LAST_CONTROL_TRANSFER: from 82916d5f to 828b27b8

STACK_TEXT: a2446f64 82916d5f 0 0 0 0 0 0 0 3 6641e18b 0 0 0 0 0 0 6 5 nt! RtlpBreakWithStatusInstruction a2446fb4 8291785d 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 8 2 9 8 2 nt! KiBugCheckDebugBreak+0x1c a2447378 828c5879 0 0 0 0 0 0 5 0 a3f00000 0 0 0 0 0 0 0 0 nt! KeBugCheck2+0x68b a24473fc 82878aa8 0 0 0 0 0 0 0 0 a3f00000 0 0 0 0 0 0 0 0 nt! MmAccessFault+0x104 a24473fc 82a6a05e 0 0 0 0 0 0 0 0 a3f00000 0 0 0 0 0 0 0 0 nt! KiTrap0E+0xdc a24474c8 975dbb32 86e819c0 004474ec 00721e00 nt! CcMapData+0xae a24474f4 975d9e1d a2b52fb8 85dad920 0 0 0 0 1 0 0 0 fastfat! FatReadVolumeFile+0x3a a2447580 975da534 a2b52fb8 a2447524 0 0 0 0 0 0 0 2 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 8 2 2 7 5 6 2 0 93528e90 93528e90 fastfat! FatFsdFileSystemControl+0x82 a2447804 8286ebd5 0 0 0 0 0 0 0 1 93528ff4 8 2 2 7 5 6 2 0 nt! IovCallDriver+0x258 a2447818 85499a56 270d61d5 8229bde8 93528e90 nt! IofCallDriver+0x1b a2447878 85499c5b 8229bde8 93528e90 86f2c678 got! FltpFsControlMountVolume+0x180 a24478a8 82b696c3 8229bde8 93528e90 93528e90 got! FltpFsControl+0x5b a24478cc 8286ebd5 0 0 0 0 0 0 0 1 8296fb88 8229bde8 nt! IovCallDriver+0x258 a24478e0 829d1dd9 8 2 8 0 4 8 7 0 8a9b0da8 8 2 8 0 4 9 0 0 nt! IofCallDriver+0x1b a2447944 828df92e 8a9b0da8 85dac000 0 0 0 0 0 0 0 0 nt! IopMountVolume+0x1d8 a244797c 82a7ddfb 85dac008 a2447aa8 a2447a40 nt! IopCheckVpbMounted+0x64 a2447a60 82a5dd1e 8a9b0da8 851cfde8 85d66750 nt! IopParseDevice+0x7db a2447adc 82a6e147 0 0 0 0 0 0 0 0 a2447b30 0 0 0 0 0 0 4 0 nt! ObpLookupObjectName+0x4fa a2447b38 82a64c25 02effc44 851cfde8 828b1d01 nt! ObOpenObjectByName+0x165 a2447bb4 82a884a4 02effca0 0 0 1 0 0 0 8 1 02effc44 nt! IopCreateFile+0x673 a2447c00 828758c6 02effca0 0 0 1 0 0 0 8 1 02effc44 nt! NtCreateFile+0x34 a2447c00 776170f4 02effca0 0 0 1 0 0 0 8 1 02effc44 nt! KiSystemServicePostCall 02effc00 7 7 6 1 5 6 1 4 7573a9d9 02effca0 0 0 1 0 0 0 8 1 ntdll! KiFastSystemCallRet 02effc04 7573a9d9 02effca0 0 0 1 0 0 0 8 1 02effc44 ntdll! ZwCreateFile+0xc 02effca8 772ce99f 0 0 0 0 4 0 0 0 0 0 1 0 0 0 8 1 0 0 0 0 0 0 0 7 KERNELBASE! CreateFileW+0x35e 02effcd4 761a2fc5 03cc0038 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 7 kernel32! CreateFileWImplementation+0x69 02effd38 761a2bc9 03cc0038 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 SHELL32! CLocalInterruptSource::v_CreateEvent+0x41 02effd5c 761aac0f 0368f598 0 0 0 0 0 0 0 0 02effd94 SHELL32! CFSInterruptSource::GetEvent+0x7b 02effd9c 761aa92a 02effdc0 0 0 0 0 0 0 0 0 006e7a90 SHELL32! CChangeNotify::_GetInterruptEvents+0x93 02effdc8 7611561b 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 7 SHELL32! CChangeNotify::_MessagePump+0x67 02effde0 75fd43c0 006e7a90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SHELL32! CChangeNotify::s_ThreadProc+0x4f 02effe68 772cee1c 0201ed74 02effeb4 776337eb WITH! WrapperThreadProc+0x1b5 02effe74 776337eb 0201ed74 758640f9 0 0 0 0 0 0 0 0 kernel32! BaseThreadInitThunk+0xe 02effeb4 776337be 75fd42ed 0201ed74 0 0 0 0 0 0 0 0 ntdll!__ RtlUserThreadStart+0x70 02effecc 0 0 0 0 0 0 0 0 75fd42ed 0201ed74 0 0 0 0 0 0 0 0 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 --------- Vulnerability code: \wrk-v1. 2\base\ntos\cache\pinsup. c Line 7 2: 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 1 5 5: ULONG PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES((ULongToPtr(FileOffset->LowPart)), Length); PETHREAD Thread = PsGetCurrentThread(); BOOLEAN ReturnStatus;

DebugTrace(+1, me, "CcMapData\n", 0 );

MmSavePageFaultReadAhead( Thread, &SavedState );

ReturnStatus = CcMapDataCommon( FileObject, FileOffset, Length, Flags, &TempBcb, Buffer ); ... Line 1 9 3 // // Loop to touch each page //

BaseAddress = *Buffer;

while (PageCount != 0) {

MmSetPageFaultReadAhead( Thread, PageCount - 1 );

ch = ((volatile UCHAR )(BaseAddress)); //

BaseAddress = (PCHAR) BaseAddress + PAGE_SIZE; PageCount -= 1; } PageCount based on the control of the length value is calculated, in this case(read the FATx)comprises: Sectors per FAT * Bytes per sector kd> . frame /c 5 kd> dd ebp+1 0 L1 //get Length value f53e1510 00721e00 kd> ? 00721e00 / 0x200(= Bytes per sector) Evaluate the expression: 1 4 6 0 7 = 0000390f (= Sectors per FAT) FileOffset is also equal to: kd> dt _LARGE_INTEGER poi(ebp+c) nt! _LARGE_INTEGER 0x200 +0x000 LowPart : 0x200 +0x004 HighPart : 0 +0x000 u : __unnamed +0x000 QuadPart : 5 1 2 Call PageCount calculation of these values: Evaluate the expression: 1 8 2 6 = 0 0 0 0 0 7 2 2 while iteration of the loop, by PAGE_SIZE to increase the BaseAddress of the pointer. So in this case the memory region will be“covered”: the kd> ? (0x722 * 0x1000) / 0x400 ------------^-----------^----------^---- PageCount PAGE_SIZE 1KB

Evaluate expression: 7 3 0 4 = 00001c88 kd> ? 00001c88 / 0x400 Evaluate expression: 7 = 0 0 0 0 0 0 0 7 ~ 7MB The next test we are able to cache how many bytes: \wrk-v1. 2\base\ntos\cache\pinsup. c Line 2 4 1: BOOLEAN CcMapDataCommon ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID Bcb, OUT PVOID Buffer )

... Line 3 5 0: // // Get pointer to the 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 an IF ?

} In CcGetVirtualAddress detected ReceiveLength: the \wrk-v1. 2\base\ntos\cache\vacbsup. c Line 3 8 8: ULONG VacbOffset = FileOffset. LowPart & (VACB_MAPPING_GRANULARITY - 1); ... Line 4 4 9: *ReceivedLength = VACB_MAPPING_GRANULARITY - VacbOffset; VACB_MAPPING_GRANULARITY value is how much? \wrk-v1. 2\base\ntos\inc\cache. h Line 3 1:

define VACB_MAPPING_GRANULARITY (0x40000)From the above code snippet to know ReceiveLength should be greater than or equal to 0×4 0 0 0 0 bytes which is 256KB.

MSDN CcMapData Official Microsoft CcMapData document[point I] In the cache Manager CcMapData not by the view boundary map data, the system cache Manager to the file in the standard size of 2 5 6 KB(the cache Manager's view size is achieved by the system defined constant VACB_MAPPING_GRANULARITY specified, the size in the ntifs. h is set to 2 5 to 6 KB), the mapped region can not exceed 2 5 6 KB. Therefore, the maximum map area is 2 5 6 KB, from file offset from 2 5 6 KB to start. Code and documentation are clear that the map file data cannot exceed 2 5 6 KB, in our example the kernel greater than 7M of the available space, iterations of this over 2 5 6 KB will lead to a crash. Why is there this BUG The length of the value of the lack of verification will lead this iteration of the infinite loop \wrk-v1. 2\base\ntos\cache\pinsup. c Line 1 9 8

while (PageCount != 0) {

MmSetPageFaultReadAhead( Thread, PageCount - 1 );

ch = ((volatile UCHAR )(BaseAddress)); // Exceeds the available mapped/assigned area Not every time triggered In the experiment I found that not each of the Sectors per FAT value is more than 0×0 2 0 0 which leads to a crash, for example, Sectors per FAT is set to 0×4 0 0 0 is an exception! FatCommonRead: Stack trace: Sectors per FAT == 4 0 0 0 Windows XP SP3 ChildEBP RetAddr Args to Child bad46fc0 b7e0d505 86a69e50 bad46fec 804e24f1 Fastfat! FatExceptionFilter+0x5 bad46fcc 804e24f1 bad46ff4 0 0 0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 Fastfat! FatFsdRead+0x13d bad47538 804f95d8 0 0 0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 c7fc0000 0 0 0 0 0 0 0 0 nt! MmAccessFault+0x5bc bad47630 8056d716 0 0 0 0 0 0 0 0 c7fc0000 0 0 0 0 0 0 0 0 nt! KiTrap0E+0xcc bad47708 b7e15b25 86a501e8 bad47734 0 0 0 0 1 0 0 0 nt! CcMapData+0xef bad4773c b7e1e8b6 86a84e28 8698b3a8 0 0 0 0 0 0 0 0 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 5 3 push ebx kd> . exr poi(poi(ebp+c)) ExceptionAddress: b7e12fc4 (Fastfat! FatCommonRead+0x0000066b) ExceptionCode: c000000d // STATUS_INVALID_PARAMETER ExceptionFlags: 0 0 0 0 0 0 0 1 NumberParameters: 0 I didn't go deep, of course, will not be noted in the code which place the cause of this exception. So I guess may be there is already a length validation, but the precision is not enough! **