CVE-2014-4115
An exploitable local privileged code execution vulnerability exists in the Microsoft Windows FastFAT system driver. The FastFAT system driver is responsible for handling FAT32 disk partitions. An attacker who can control the NumberOfFATs value of a FAT32 boot sector can cause an undersized allocation which can later be used to write controlled data into the kernel pool.
Windows XP SP3 Vulnerable
Windows 7 Not Vulnerable
Windows 8 Not Vulnerable
http://windows.microsoft.com/
The FatCommonWrite function in FastFAT.sys is responsible for parsing the FAT32 boot sector. The boot sector contains a BIOS Parameter Block which is represented in the partial BPB_FAT32 structure below:
Member "Value (dec)" "Value (hex)" Size
"00000000 struct BOOTSECTOR_FAT32" {...} 00000200
" 00000000 int8 jmp[00000003]" 00000003
" 00000003 char OemName[00000008]" MSDOS5.0 00000008
" 0000000B struct BPB_FAT32" {...} 00000035
" 0000000B uint16 BytesPerSector" 512 0200 00000002
" 0000000D int8 SectorsPerCluster" 1 01 00000001
" 0000000E uint16 ReservedSectors" 36 0024 00000002
" 00000010 int8 NumberOfFATs" 1 01 00000001
-- snip --
The below pseudo code is responsible for parsing part of the BIOS Parameter Block. The first clause shows that the NumberOfFATs value, if greater than ‘2’, is used as the size of a kernel pool allocation:
1 NumberOfFATs = *(_BYTE *)(VCB + 150);
2 if ( NumberOfFATs <= 2u )
3 {
4 ptrPool = &v100;
5 }
6 else
7 {
8 ptrPool = ExAllocatePoolWithTag((POOL_TYPE)17, NumberOfFATs, 'itaF');
9 v14 = VCB;
10 }
As we continue, the function also performs a loop using the NumberOfFATs value as the iteration count:
11 counter = 0;
12 if ( *(_BYTE *)(v14 + 0x96) )
13 {
14 v18 = offsetToFirstFAT;
15 unknow1 = offsetToFirstFAT - unknow2;
16 v20 = (int)((char *)ptrPool + 12);
17 do
18 {
19 *(_DWORD *)(v20 - 4) = offsetToFirstFAT;
20 *(_DWORD *)(v20 - 12) = v18;
21 *(_DWORD *)(v20 - 8) = 0;
22 *(_DWORD *)v20 = unknow1;
23 *(_DWORD *)(v20 + 4) = unknow3;
24 ++counter;
25 v18 += BytesPerFat;
26 v20 += 24;
27 }
28 while ( counter < NumberOfFATs );
29 }
Within the loop, the code expects there to be an array of 24-byte structures in the allocated buffer for each FAT indicated by the NumberOfFATs field. Since the allocation size was not multiplied by the size of the structure, memory will be written outside the bounds of the buffer.
eax=8a01100c ebx=8a7ece90 ecx=00186c00 edx=00000800 esi=89a14b18 edi=00004800
eip=b7ae63da esp=bacdf934 ebp=bacdfab4 iopl=0 nv up ei ng nz ac pe cy
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010297
Fastfat!FatCommonWrite+0x444:
b7ae63da 8978fc mov dword ptr [eax-4],edi ds:0023:8a011008=????????
STACK_TEXT:
bacdf848 8051cc4f 00000050 8a011008 00000001 nt!KeBugCheckEx+0x1b
bacdf8a8 8054051c 00000001 8a011008 00000000 nt!MmAccessFault+0x8e7
bacdf8a8 b7ae63da 00000001 8a011008 00000000 nt!KiTrap0E+0xcc
bacdfab4 b7adab9a 89a14b18 8a7ece90 89c59020 Fastfat!FatCommonWrite+0x444
bacdfaf8 804ee119 89c59020 8a7ece90 806d12a4 Fastfat!FatFsdWrite+0xad
bacdfb08 8064d628 89ada170 00004000 89c59020 nt!IopfCallDriver+0x31
bacdfb2c 804ef411 bacdfb68 bacdfd40 00000000 nt!IovCallDriver+0xa0
bacdfb40 8050c497 89ada107 bacdfb68 bacdfbfc nt!IoSynchronousPageWrite+0xaf
bacdfc24 8050ce3d e10ec820 e10ec828 e10ec828 nt!MiFlushSectionInternal+0x3bf
bacdfc60 804e38a2 89c33d70 e10ec820 00000004 nt!MmFlushSection+0x1b5
bacdfce8 804e3bc4 00001000 00000000 00000001 nt!CcFlushCache+0x386
bacdfd2c 804e61ee 89da0290 8055b0c0 89da1da8 nt!CcWriteBehind+0xdc
bacdfd74 80534c02 89da0290 00000000 89da1da8 nt!CcWorkerThread+0x126
bacdfdac 805c6160 89da0290 00000000 00000000 nt!ExpWorkerThread+0x100
bacdfddc 80541dd2 80534b02 00000000 00000000 nt!PspSystemThreadStartup+0x34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
Marcin ‘Icewall’ Noga of Sourcefire VRT