CVE-2016-3369
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.
Windows 10, AHCACHE.SYS version 10.0.10586.0 Tested on Windows 10 X86
6.8 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:N/A:H
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 _AslpFileVerQueryValue@16 ; 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 “crash_loc” 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=STATUS_NOT_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 _AslpFileVerQueryValue@16 ; 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
*******************************************************************************
* *
* 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
---------
2016-07-11 - Initial Discovery
2016-07-25 - Vendor Notification
2016-09-13 - Patch Released
2016-09-13 - Public Disclosure
Discovered by Piotr Bania of Cisco Talos.