Talos Vulnerability Report

TALOS-2016-0191

Microsoft Windows10 AHCACHE.SYS Remote Denial Of Service

September 13, 2016
CVE Number

CVE-2016-3369

Summary

A denial of service vulnerability exists in the AHCACHE.SYS driver. A specially crafted Portable Executable file can cause a bugcheck in the Windows kernel resulting in remote denial of service.

Tested Versions

Windows 10, AHCACHE.SYS version 10.0.10586.0 Tested on Windows 10 X86

Product URLs

http://microsoft.com

CVSSv3 Score

6.8 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:N/A:H

Details

The AHCACHE.SYS driver handles local cache for application compatibility information which is used to fix application behavior on newer versions of Microsoft Windows operating system.

The bug happens in the AslpFileQueryVersionString function which is called during cache lookup (among other functions - see attached stack trace in the Crash Information section):

PAGE:00020850 crash_loc:                              ; CODE XREF: AslpFileQueryVersionStringBUG(x,x,x,x,x)+1E5j
PAGE:00020850                 push    [ebp+var_11C_arg8]
PAGE:00020856                 movzx   eax, word ptr [ecx+2] ; out of band read
PAGE:00020856                                               ; ahcache!AslpFileQueryVersionString+176
PAGE:0002085A                 push    eax
PAGE:0002085B                 movzx   eax, word ptr [ecx]
PAGE:0002085E                 push    eax
PAGE:0002085F                 push    offset pszFormat ; "\\StringFileInfo\\%04X%04X\\%s"
PAGE:00020864                 lea     eax, [ebp+pszDest]
PAGE:0002086A                 push    80h             ; cchDest
PAGE:0002086F                 push    eax             ; pszDest
PAGE:00020870                 call    _RtlStringCchPrintfW
PAGE:00020875                 mov     ebx, eax
PAGE:00020877                 add     esp, 18h
PAGE:0002087A                 test    ebx, ebx
PAGE:0002087C                 js      loc_32A83
PAGE:00020882                 mov     ecx, [ebp+a1_FileVerSection]
PAGE:00020888                 lea     eax, [ebp+a4]
PAGE:0002088E                 push    eax             ; a4
PAGE:0002088F                 lea     eax, [ebp+a3]
PAGE:00020895                 push    eax             ; a3
PAGE:00020896                 lea     edx, [ebp+pszDest] ; a2_UnicodeStringTranslation
PAGE:0002089C                 call    [email protected] ; AslpFileVerQueryValue(x,x,x,x)
PAGE:000208A1                 mov     ebx, eax
PAGE:000208A3                 test    ebx, ebx
PAGE:000208A5                 jns     short loc_208DF
PAGE:000208A7                 cmp     ebx, STATUS_NOT_FOUND
PAGE:000208AD                 jnz     loc_32A68
PAGE:000208B3                 mov     ecx, [ebp+var_10C_arg0]
PAGE:000208B9                 inc     esi
PAGE:000208BA                 add     ecx, 4
PAGE:000208BD                 mov     [ebp+var_10C_arg0], ecx
PAGE:000208C3                 cmp     esi, edi
PAGE:000208C5                 jb      short crash_loc

AslpFileQueryVersionString is called from the AslpFileMakeStringVersionAttributes function. As you can see on the code provided above the "crashloc" label is executed in a loop. Where the ESI register is the counter incremented every cycle (address 0x000208B9) and the EDI register is the maximum number of allowed loop cycles (address 0x000208C3). As you can see there is another condition that can end the loop (0x000208A7) which tests whether the wanted value was found by the AslpFileVerQueryValue however it is always passed since ebx=STATUSNOT_FOUND (assuming forged PE file is used).

The value of EDI is taken from the PE file (resource section, Var->wValueLength [1] field) through the AslpFileVerQueryValue function where the wanted sub-block argument is "\VarFileInfo\Translation" (Var identifiers are often used by applications to access a language-specific StringTable structure in the version-information resource). Just like presented below:

PAGE:0002057A                 lea     ecx, [ebp+v22_ValueLengthVersionSec]
PAGE:0002057D                 mov     edx, offset a2_UnicodeSubBlock ; a2_UnicodeSubBlock
PAGE:00020582                 push    ecx             ; a4_OutLength
PAGE:00020583                 lea     ecx, [ebp+v23_OutQuery]
PAGE:00020586                 push    ecx             ; a3_OutBuffer
PAGE:00020587                 mov     ecx, eax        ; ecx = pBlock = FileVerInfoSection
PAGE:00020589                 call    [email protected] ; AslpFileVerQueryValue(x,x,x,x)
PAGE:0002058E                 mov     edi, eax
PAGE:00020590                 cmp     edi, 0C0000225h
PAGE:00020596                 jz      loc_32A1B
PAGE:0002059C                 test    edi, edi
PAGE:0002059E                 js      loc_32A22
PAGE:000205A4                 mov     eax, [ebp+v23_OutQuery]
PAGE:000205A7
PAGE:000205A7 loc_205A7:                              ; CODE XREF: AslpFileMakeStringVersionAttributesBUG(x,x)+124CBj
PAGE:000205A7                 mov     edx, [ebp+v22_ValueLengthVersionSec]
PAGE:000205AA                 mov     ecx, ebx
PAGE:000205AC                 shr     edx, 2          ; divide by 4, final size (Var->wValueLength / 4)

Obtained maximum loops cycles value is later divided by 4 and supplied as an argument to the AslpFileQueryVersionString function and later used as the loop limit. When attacker forges this value it is possible to cause access violation exception because unavailable memory will be accessed (address 0x00020856). This happens because there are no boundary checks testing whether the obtained data from the resource section is big enough to cover extra size provided by Var->wValueLength. This causes whole system to crash and can be triggered remotely.

[1] - https://msdn.microsoft.com/en-us/library/windows/desktop/ms646994(v=vs.85).aspx

Crash Information

*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck 50, {b0798002, 0, 8db80856, 0}

Probably caused by : ahcache.sys ( ahcache!AslpFileQueryVersionString+176 )

Followup: MachineOwner
---------

nt!RtlpBreakWithStatusInstruction:
8191c1a4 cc              int     3
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: b0798002, memory referenced.
Arg2: 00000000, value 0 = read operation, 1 = write operation.
Arg3: 8db80856, If non-zero, the instruction address which referenced the bad memory
    address.
Arg4: 00000000, (reserved)

Debugging Details:
------------------


READ_ADDRESS: GetPointerFromAddress: unable to read from 00000000
GetPointerFromAddress: unable to read from 00000000
unable to get nt!MmSpecialPoolStart
unable to get nt!MmSpecialPoolEnd
unable to get nt!MmPagedPoolEnd
unable to get nt!MmNonPagedPoolStart
unable to get nt!MmSizeOfNonPagedPoolInBytes
 b0798002

FAULTING_IP:
ahcache!AslpFileQueryVersionString+176
8db80856 0fb74102        movzx   eax,word ptr [ecx+2]

MM_INTERNAL_CODE:  0

IMAGE_NAME:  ahcache.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  5632d118

MODULE_NAME: ahcache

FAULTING_MODULE: 8db70000 ahcache

DEFAULT_BUCKET_ID:  WIN8_DRIVER_FAULT

BUGCHECK_STR:  AV

PROCESS_NAME:  explorer.exe

CURRENT_IRQL:  2

ANALYSIS_VERSION: 6.3.9600.17298 (debuggers(dbg).141024-1500) amd64fre

TRAP_FRAME:  9cf2734c -- (.trap 0xffffffff9cf2734c)
ErrCode = 00000000
eax=c0000225 ebx=c0000225 ecx=b0798000 edx=00000001 esi=00001e45 edi=00003333
eip=8db80856 esp=9cf273c0 ebp=9cf274f4 iopl=0         nv up ei ng nz na pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010287
ahcache!AslpFileQueryVersionString+0x176:
8db80856 0fb74102        movzx   eax,word ptr [ecx+2]     ds:0023:b0798002=????
Resetting default scope

LAST_CONTROL_TRANSFER:  from 81995add to 8191c1a4

STACK_TEXT:
9cf26d4c 81995add 00000003 35956cec 00000065 nt!RtlpBreakWithStatusInstruction
9cf26da0 819955bd 850ff340 9cf271a4 9cf27210 nt!KiBugCheckDebugBreak+0x1f
9cf27178 8191b002 00000050 b0798002 00000000 nt!KeBugCheck2+0x742
9cf2719c 8191af39 00000050 b0798002 00000000 nt!KiBugCheck2+0xc6
9cf271bc 8193d33c 00000050 b0798002 00000000 nt!KeBugCheckEx+0x19
9cf27210 8184d446 b0798002 8184d446 9cf2734c nt! ?? ::FNODOBFM::`string'+0xba2a
9cf272a8 8192cd8c 00000000 b0798002 00000000 nt!MmAccessFault+0x4e6
9cf272a8 8db80856 00000000 b0798002 00000000 nt!KiTrap0E+0xec
9cf274f4 8db805d7 b07906ec 00003333 8db8cb42 ahcache!AslpFileQueryVersionString+0x176
9cf27530 8db80524 00000400 0000000a 00000000 ahcache!AslpFileMakeStringVersionAttributes+0x85
9cf27550 8db7d921 00038de4 b06ec568 00000016 ahcache!AslpFileGetVersionAttributes+0x42
9cf27570 8db7d459 00000400 00000000 00000000 ahcache!AslFileAllocAndGetAttributes+0xa1
9cf275bc 8db7daa1 7eadc44c 00038dd6 8a97c7b8 ahcache!SdbpCheckAllAttributes+0x2a9
9cf27600 8db7cdf2 9cf27638 b07945b8 b06ec568 ahcache!SdbpCheckMatchingFiles+0x79
9cf2763c 8db7c9b6 b06ec568 00038d8c 9cf27748 ahcache!SdbpMatchList+0x68
9cf27670 8db7caa0 00038d8c 9cf27748 9cf2769c ahcache!SdbpCheckForMatch+0x50
9cf276a0 8db7c7dc 00038d8c 9cf2771c 9cf27748 ahcache!SdbpCheckExe+0x7c
9cf27720 8db7a34b 51b31172 9cf27748 9cf277c4 ahcache!SdbpSearchDB+0x94
9cf27864 8db7aef0 51b31172 8a9d96f8 8a92e0a8 ahcache!SdbGetMatchingExeEx+0x20d
9cf27898 8db7a822 9cf2797c 9cf27950 9cf27948 ahcache!AhcpSdbQueryLookupExe+0x58
9cf278fc 8db8103c 9cf2797c 9cf27950 9cf27948 ahcache!AhcSdbQueryLookup+0x5a
9cf27980 8db7ebc1 8d862d80 a686d958 80001318 ahcache!AhcpCacheBuildSdbInfo+0x12e
9cf27a0c 8db7e2d5 8d862d80 9cf27a50 80001318 ahcache!AhcCacheLookup+0x7e1
9cf27a70 8db7dedb 00000000 0d94e29c 0000000c ahcache!AhcApiLookup+0xa5
9cf27b90 8db7dd36 00000001 00000000 8d4bfec8 ahcache!AhcDispatch+0x17b
9cf27ba4 818493c3 8d4bfec8 8aaebd20 00000000 ahcache!AhcDriverDispatchDeviceControl+0x36
9cf27bc0 81ab9321 00000000 0d94e1d0 81ab927a nt!IofCallDriver+0x43
9cf27c04 81929787 00000000 0d94e1e0 0d94e4c8 nt!NtApphelpCacheControl+0xa7
9cf27c04 778113f0 00000000 0d94e1e0 0d94e4c8 nt!KiSystemServicePostCall
0d94e1bc 7781087a 74fa0ffb 00000000 0d94e1e0 ntdll!KiFastSystemCallRet
0d94e1c0 74fa0ffb 00000000 0d94e1e0 00000000 ntdll!NtApphelpCacheControl+0xa
0d94e4c8 74fa0e6c 09a469d0 00001b4c 0d94e5e0 KERNEL32!CompatCachepGetFlags+0xe7
0d94e4f8 74fa0d45 0d94e5e0 00000000 0d94e5a8 KERNEL32!BaseCheckDetectionMethods+0x83
0d94e548 74fa5517 ffffffff 00001b4c 09a469d0 KERNEL32!BaseCheckElevation+0x85
0d94e5b8 75a15658 09a469d0 0d94e5e0 00000000 KERNEL32!CheckElevation+0xb7
0d94e5f0 75bba392 09a469d0 0d94eaa8 75bba300 SHELL32!IsElevationRequired+0x68
0d94e608 759ad50f 00000202 0d94e880 00000104 SHELL32!CFSFolderExtractIcon::_GetIconLocationW+0x92
0d94e630 758514ea 099ca2d4 00000202 0d94e880 SHELL32!`SharedModelTelemetryLogging::Instance'::`2'::`dynamic atexit destructor for 'wrapper''+0x3103f
0d94ea90 758512e9 0d94f624 757d045c 09a50ae8 SHELL32!_GetILIndexGivenPXIcon+0x1cb
0d94ead0 75920b15 00000200 0d94f624 0d94f624 SHELL32!_GetILIndexFromItem+0x6c11
0d94f5c4 7590578a 0d94f5f8 748ed42d 09a50aec SHELL32!CFSFolder::GetIconOf+0x3b2
0d94f5f8 74806b86 09a366d8 00000200 0d94f624 SHELL32!CAggregatedUnknown::CUnkInner::QueryInterface+0x8a
0d94f62c 74807ebf 00000200 0d94f654 00000000 windows_storage!MapIDListToIconILIndex+0x47
0d94f670 7480a9b4 09ad0198 00800000 7480a8c0 windows_storage!CLoadSystemIconTask::InternalResumeRT+0x10f
0d94f698 7480a647 09ad0198 09936168 09957c48 windows_storage!CRunnableTask::Run+0xf4
0d94f6b4 748096d1 0d94f6d4 0a179b08 09936168 windows_storage!CShellTask::TT_Run+0x7f
0d94f700 7480814b 74808120 0d94f724 77463304 windows_storage!CShellTaskThread::ThreadProc+0xa4
0d94f70c 77463304 09936168 00000000 00000000 windows_storage!CShellTaskThread::s_ThreadProc+0x2b
0d94f724 777a9de4 0a179b08 4c4efbb7 777a9c90 SHCORE!ExecuteWorkItemThreadProc+0x24
0d94f85c 777b5a2b 0d94f96c 09955ee8 4c4ef98f ntdll!RtlpTpWorkCallback+0x154
0d94fa64 74f995f4 04542400 74f995d0 fbdb3d78 ntdll!TppWorkerThread+0x8fb
0d94fa78 777a241a 04542400 4c4ef92b 00000000 KERNEL32!BaseThreadInitThunk+0x24
0d94fac0 777a23e9 ffffffff 77823a01 00000000 ntdll!__RtlUserThreadStart+0x2b
0d94fad0 00000000 777b5130 04542400 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  kb

FOLLOWUP_IP:
ahcache!AslpFileQueryVersionString+176
8db80856 0fb74102        movzx   eax,word ptr [ecx+2]

SYMBOL_STACK_INDEX:  8

SYMBOL_NAME:  ahcache!AslpFileQueryVersionString+176

FOLLOWUP_NAME:  MachineOwner

BUCKET_ID_FUNC_OFFSET:  176

FAILURE_BUCKET_ID:  AV_ahcache!AslpFileQueryVersionString

BUCKET_ID:  AV_ahcache!AslpFileQueryVersionString

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:av_ahcache!aslpfilequeryversionstring

FAILURE_ID_HASH:  {15a45ea2-24fe-4d5e-5471-e3b0628a1e8e}

Followup: MachineOwner
---------

Timeline

2016-07-11 - Initial Discovery
2016-07-25 - Vendor Notification
2016-09-13 - Patch Released
2016-09-13 - Public Disclosure

Credit

Discovered by Piotr Bania of Cisco Talos.