Talos Vulnerability Report

TALOS-2018-0568

Intel Unified Shader Compiler for Intel Graphics Accelerator Remote Denial Of Service

October 9, 2018
CVE Number

CVE-2018-12153

Summary

An exploitable denial-of-service vulnerability exists in the Intel’s Unified Shader Compiler for Intel(R) Graphics Accelerator (10.18.14.4889). A specially crafted pixel shader can cause denial-of-service issues. An attacker can provide a specially crafted shader file (either in binary or text form) to trigger this vulnerability. This vulnerability can be triggered from VMware guest, and VMware host will be affected (leading to vmware-vmx.exe process crash on host).

Tested Versions

Intel igdusc64.dll 10.18.14.4889 (x64) on Windows 8.1 x64 VMware Workstation 14 (14.0.0 build-6661328) with Windows 8.1 x64 as guestVM

Product URLs

http://intel.com

CVSSv3 Score

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

CWE

CWE-131: Incorrect Calculation of Buffer Size

Details

This vulnerability can be triggered by supplying a malformed pixel shader (in text or binary form) to the Intel igdusc64.dll driver. Such an attack can be triggered from local machine (usermode), from VMware guest usermode (to trigger the bug on VMware host) or theoretically through WEBGL (remote website) — assuming the browser will not use ANGLE and somehow supply the malformed shader to the vulnerable Intel driver.

By supplying a specially generated shader file, an attacker can force the igdusc64.dll to execute the “memcpy_s” function with arguments that trigger an exception, which later forces termination of the program in order to prevent memory corruption.

The initial problem starts when there is no proper validation of the return value provided by “sub_483870”. This value will be later used in the “sub_34BC30” in a while loop condition (maximum value of iterations). By supplying a malformed shader, an attacker can force this value to be 0xFFFFFFFF (-1), and therefore force the while loop in “sub_34BC30” to iterate a large number of times. Every iteration “sub_0x1E9A0” is called, fragments of which are provided below:

.text:000000000001E9E7                 lea     eax, ds:0[rbx*4]       										[1]
.text:000000000001E9EE                 mov     ecx, eax        ; Size (32bit value)
.text:000000000001E9F0                 mov     r14d, eax
.text:000000000001E9F3                 call    malloc
.text:000000000001E9F8                 mov     rbp, rax
.text:000000000001E9FB                 test    rax, rax
.text:000000000001E9FE                 jz      short loc_1EA3B
.text:000000000001EA00                 mov     r8d, r14d       ; Size
.text:000000000001EA03                 xor     edx, edx        ; Val
.text:000000000001EA05                 mov     rcx, rax        ; Dst
.text:000000000001EA08                 call    memset
.text:000000000001EA0D                 mov     r8, [rsi+18h]   ; Src
.text:000000000001EA11                 test    r8, r8
.text:000000000001EA14                 jz      short loc_1EA31
.text:000000000001EA16                 mov     r9d, [rsi+20h]  ; src size (count) 32-bit value
.text:000000000001EA1A                 mov     edx, r14d       ; DstSize
.text:000000000001EA1D                 mov     rcx, rbp        ; Dst
.text:000000000001EA20                 shl     r9, 2           ; src size << 2 -> extended to 64-bits [2]
.text:000000000001EA24                 call    memcpy_s        ; memcpy_s(
.text:000000000001EA24                                         ;    void *dest,
.text:000000000001EA24                                         ;    size_t destSize,
.text:000000000001EA24                                         ;    const void *src,
.text:000000000001EA24                                         ;    size_t count
.text:000000000001EA24                                         ; )
.text:000000000001EA24                                         ;
.text:000000000001EA24                                         ;
.text:000000000001EA24                                         ; rcx - dest
.text:000000000001EA24                                         ; rdx - dest size
.text:000000000001EA24                                         ; r8  - src
.text:000000000001EA24                                         ; r9  - src size (count)

Please note that at [1], the LEA instruction is used to calculate the final size for the malloc call. This is done by multiplying RBX register by 4 and truncating the result to a 32-bit value (the result is later stored in ECX / R14D). As you can see, the instruction at 0x1EA20 calculates the source size (count) parameter for the memcpy_s function. The initial 32-bit value is taken from [rsi+0x20] memory and is multiplied later by shifting left at [2] (shl 2 / fast multiply by 4) but the result of this operation is a 64-bit value, not 32-bit, and it is stored in the R9 register.

By supplying the malformed pixel shader, an attacker can force the Intel igdusc64.dll driver to allocate memory with size 0 (calculated size parameter passed to malloc will be 0 due to 32-bit number limitations) but the src size (count) parameter passed to the memcpy_s function will be much bigger (0x0000000080000000). If the normal memcpy function would have been used that could cause a memory corruption, but since the memcpy_s function is used in, the incorrect parameter will be detected and the exception will be thrown which will result in the application being terminated.

...
before memcpy_s: [i=33] rcx(dest)=0x0000001ddcea7040 rdx(dest_size)=0x10000000 r8(src)=0x0000001dd4e95040 r9(count)=0x0000000008000000 [rsi+20h]=0x02000000 
after memcpy_s: returned 0x00000000 
przed memcpy_s: rbx=0x0000000008000000 eax=rbx*4=0x20000000 
before memcpy_s: [i=34] rcx(dest)=0x0000001d8000c040 rdx(dest_size)=0x20000000 r8(src)=0x0000001ddcea7040 r9(count)=0x0000000010000000 [rsi+20h]=0x04000000 
after memcpy_s: returned 0x00000000 
przed memcpy_s: rbx=0x0000000010000000 eax=rbx*4=0x40000000 
before memcpy_s: [i=35] rcx(dest)=0x0000001dccf1d040 rdx(dest_size)=0x40000000 r8(src)=0x0000001d8000c040 r9(count)=0x0000000020000000 [rsi+20h]=0x08000000 
after memcpy_s: returned 0x00000000 
przed memcpy_s: rbx=0x0000000020000000 eax=rbx*4=0x80000000 
before memcpy_s: [i=36] rcx(dest)=0x0000001e0cf2a040 rdx(dest_size)=0x80000000 r8(src)=0x0000001dccf1d040 r9(count)=0x0000000040000000 [rsi+20h]=0x10000000 
after memcpy_s: returned 0x00000000 
przed memcpy_s: rbx=0x0000000040000000 eax=rbx*4=0x00000000 
before memcpy_s: [i=37] rcx(dest)=0x0000001dccad8af0 rdx(dest_size)=0x00000000 r8(src)=0x0000001e0cf2a040 r9(count)=0x0000000080000000 [rsi+20h]=0x20000000 

0:000> g
(41c8.26d0): Security check failure or stack buffer overrun - code c0000409 (!!! second chance !!!)
igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+0x2323:
00007ffc`013697c3 cd29            int     29h

Crash Information

0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SYSTEM32\igd10iumd64.dll - 

DUMP_CLASS: 2

DUMP_QUALIFIER: 0

FAULTING_IP: 
igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+2323
00007ffc`013697c3 cd29            int     29h

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ffc013697c3 (igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+0x0000000000002323)
   ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: 0000000000000005
Subcode: 0x5 FAST_FAIL_INVALID_ARG

FAULTING_THREAD:  000026d0

PROCESS_NAME:  POC_EXEC_SHADER.exe

ERROR_CODE: (NTSTATUS) 0xc0000409 - <Unable to get error code text>

EXCEPTION_CODE: (NTSTATUS) 0xc0000409 - <Unable to get error code text>

EXCEPTION_CODE_STR:  c0000409

EXCEPTION_PARAMETER1:  0000000000000005

WATSON_BKT_PROCSTAMP:  5aaff6e9

WATSON_BKT_MODULE:  igdusc64.dll

WATSON_BKT_MODSTAMP:  5a32f1cc

WATSON_BKT_MODOFFSET:  997c3

WATSON_BKT_MODVER:  10.18.14.4889

MODULE_VER_PRODUCT:  Intel HD Graphics Drivers for Windows 8(R)

BUILD_VERSION_STRING:  6.3.9600.17415 (winblue_r4.141028-1500)

MODLIST_WITH_TSCHKSUM_HASH:  20e3a9569894c2d493762eac712fad7b6fab693e

MODLIST_SHA1_HASH:  bda2d4950a1660ae4a44fc3b80dcd66d3bc070ce

NTGLOBALFLAG:  70

APPLICATION_VERIFIER_FLAGS:  0

PRODUCT_TYPE:  1

SUITE_MASK:  272

DUMP_TYPE:  fe

ANALYSIS_SESSION_HOST:  SPLINTER

ANALYSIS_SESSION_TIME:  03-21-2018 13:30:30.0896

ANALYSIS_VERSION: 10.0.15063.468 amd64fre

THREAD_ATTRIBUTES: 
OS_LOCALE:  PLK

PROBLEM_CLASSES: 

    ID:     [0n262]
    Type:   [FAIL_FAST]
    Class:  Primary
    Scope:  DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
            BUCKET_ID
    Name:   Add
    Data:   Omit
    PID:    [Unspecified]
    TID:    [Unspecified]
    Frame:  [0]

    ID:     [0n251]
    Type:   [INVALID_ARG_FAILURE]
    Class:  Addendum
    Scope:  DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
            BUCKET_ID
    Name:   Add
    Data:   Omit
    PID:    [Unspecified]
    TID:    [Unspecified]
    Frame:  [0]

    ID:     [0n111]
    Type:   [EXPLOITABLE]
    Class:  Addendum
    Scope:  DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
            BUCKET_ID
    Name:   Add
    Data:   Omit
    PID:    [0x41c8]
    TID:    [0x26d0]
    Frame:  [0] : igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>

BUGCHECK_STR:  FAIL_FAST_INVALID_ARG_FAILURE_EXPLOITABLE

DEFAULT_BUCKET_ID:  FAIL_FAST_INVALID_ARG_FAILURE_EXPLOITABLE

PRIMARY_PROBLEM_CLASS:  FAIL_FAST

LAST_CONTROL_TRANSFER:  from 00007ffc01369788 to 00007ffc013697c3

STACK_TEXT:  
0000001d`c9babff0 00007ffc`01369788 : 0000001d`c9bac1b4 00000000`0d8a60f4 00000000`40000000 00007ffc`0136c848 : igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+0x2323
0000001d`c9bac020 00007ffc`013697a5 : 00000000`00000022 0000001d`ccad8af0 0000001e`0cf2a040 00000000`00000000 : igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+0x22e8
0000001d`c9bac060 00007ffc`01367c67 : 00000000`0000023c 0000001d`00000004 0000001d`c9ddd9b8 00000000`0000023c : igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+0x2305
0000001d`c9bac0a0 00007ffc`012dea29 : 00000000`40000000 0000001d`c9ddd9b8 00000000`00000001 00000000`00000003 : igdusc64!USC::DeleteCompilerOutputPixelShaderOpenGL_impl<USC::SCompilerOutputPixelShaderOpenGL_Gen9>+0x7c7
0000001d`c9bac0d0 00007ffc`0160be94 : 00000000`20000000 00000000`ffffffff 0000001d`c9bac228 0000001d`c9ddd900 : igdusc64!USC::CShaderInputDecl::GetVertexIDRegisterNum+0xcb69
0000001d`c9bac100 00007ffc`01744570 : 0000001d`00000001 0000001d`ccb425a8 0000001d`0000015e 0000001d`ccb21254 : igdusc64!USC::SetClientCallbacks+0x250f34
0000001d`c9bac160 00007ffc`0173dce9 : 00000000`00000001 00000000`0000023c 00000000`00000001 0000001d`c9bac478 : igdusc64!USC::SetClientCallbacks+0x389610
0000001d`c9bac350 00007ffc`0173c542 : 0000001d`ccb21254 0000001d`cca9f290 00000000`0000023c 0000001d`ccb42468 : igdusc64!USC::SetClientCallbacks+0x382d89
0000001d`c9bac3e0 00007ffc`0173b544 : 0000001d`ccae5b50 0000001d`c9bac600 0000001d`ccb42468 0000001d`cca9f8b0 : igdusc64!USC::SetClientCallbacks+0x3815e2
0000001d`c9bac510 00007ffc`0173bd63 : 0000001d`ccae5b50 0000001d`c9bac650 00000000`00000001 0000001d`cca9f8b0 : igdusc64!USC::SetClientCallbacks+0x3805e4
0000001d`c9bac590 00007ffc`01735157 : 0000001d`00000001 00000000`00000001 0000001d`ccae5660 0000001d`cca9f8b0 : igdusc64!USC::SetClientCallbacks+0x380e03
0000001d`c9bac650 00007ffc`01735c41 : 00000000`00000081 00000000`00000001 00007ffc`01c54ad6 0000001d`c9e17880 : igdusc64!USC::SetClientCallbacks+0x37a1f7
0000001d`c9bac6b0 00007ffc`01730fcf : 00000000`00000001 0000001d`ccae70a0 0000001d`c9e175f0 0000001d`ccae5660 : igdusc64!USC::SetClientCallbacks+0x37ace1
0000001d`c9bac6f0 00007ffc`017ceca9 : 00000000`00000001 00000000`00000001 00000000`00000001 00000000`00000000 : igdusc64!USC::SetClientCallbacks+0x37606f
0000001d`c9bac8b0 00007ffc`013e6707 : 0000001d`00000000 0000001d`00000001 0000001d`c9dd7d40 0000001d`00000001 : igdusc64!USC::getInitShaderWriteMask+0x22409
0000001d`c9bacad0 00007ffc`013e6bf9 : 00000000`00000001 00007ffc`00000001 0000001d`c9d80001 00000000`00000000 : igdusc64!USC::SetClientCallbacks+0x2b7a7
0000001d`c9bacc00 00007ffc`013e8956 : 0000001d`c9bacd00 0000001d`c9bacd00 00000000`00000001 0000001d`c9dd1d00 : igdusc64!USC::SetClientCallbacks+0x2bc99
0000001d`c9baccb0 00007ffc`013e9043 : 0000001d`00000000 0000001d`00000001 0000001d`c9bace70 00000000`00000001 : igdusc64!USC::SetClientCallbacks+0x2d9f6
0000001d`c9bacd50 00007ffc`013e9274 : 00000000`00000001 0000001d`00000001 0000001d`c9bad170 00007ffc`01760131 : igdusc64!USC::SetClientCallbacks+0x2e0e3
0000001d`c9bacdd0 00007ffc`0175ef3e : 00000000`00000001 0000001d`c9bacf50 0000001d`c9dd1d10 00000000`00000300 : igdusc64!USC::SetClientCallbacks+0x2e314
0000001d`c9bace50 00007ffc`01318907 : 00000001`c9d92001 0000001d`c9dd1080 0000001d`c9bad7d8 0000001d`c9d80000 : igdusc64!USC::SetClientCallbacks+0x3a3fde
0000001d`c9bad080 00007ffc`01320eeb : 00003900`00000000 00003900`00000000 00003900`00000000 00000001`00000000 : igdusc64!OpenCompiler12+0x4267
0000001d`c9bad120 00007ffc`013230ef : 00000000`00000001 0000001d`c9d9204c 0000001d`c9bad7d8 0000001d`c9dc01b0 : igdusc64!OpenCompiler12+0xc84b
0000001d`c9bad490 00007ffc`0131ecd4 : 0000001d`c9dceb00 00000000`00000000 0000001d`c9bad800 00000000`00000001 : igdusc64!OpenCompiler12+0xea4f
0000001d`c9bad580 00007ffc`02fbc43c : 00007ffc`03759580 0000001d`c9bad800 00000000`00000001 00000000`00000001 : igdusc64!OpenCompiler12+0xa634
0000001d`c9bad5e0 00007ffc`0371cce8 : 00007ffc`00000080 0000001d`00000001 00007ffc`03759580 00007ffc`03759580 : igd10iumd64!OpenAdapter10_2+0x3ae83c
0000001d`c9bad700 00007ffc`0371c7c1 : 0000001d`c9db7340 0000001d`c9dad5a0 0000001d`c9badda8 00000000`00000000 : d3d11!CPixelShader::CLS::FinalConstruct+0x238
0000001d`c9bad8c0 00007ffc`0371c6d0 : 0000001d`c9dd0990 0000001d`c9dd0940 00007ffc`03753448 0000001d`c9badda8 : d3d11!CLayeredObjectWithCLS<CPixelShader>::FinalConstruct+0xd5
0000001d`c9bad930 00007ffc`0371c5a7 : 0000001d`c9dd0990 0000001d`c9dd0990 00000000`00000009 0000001d`c9baf140 : d3d11!CLayeredObjectWithCLS<CPixelShader>::CreateInstance+0x11c
0000001d`c9bad990 00007ffc`03707fdd : 00000000`00000000 00000000`00000009 00000000`00000000 0000001d`c9baf110 : d3d11!CDevice::CreateLayeredChild+0x1cff
0000001d`c9baef50 00007ffc`03707e39 : 0000001d`c9dd0958 00000000`00000009 0000001d`c9baf4c8 00000000`00000003 : d3d11!NDXGI::CDevice::CreateLayeredChild+0x222
0000001d`c9baf0d0 00007ffc`0371ca78 : 0000001d`c9dab610 0000001d`00000009 0000001d`c9dab610 0000001d`c9baf3b0 : d3d11!NOutermost::CDevice::CreateLayeredChild+0x281
0000001d`c9baf290 00007ffc`0371c9d8 : 0000001d`c9d91fb0 0000001d`00000000 0000001d`c9baf510 00000000`00000000 : d3d11!CDevice::CreateAndRecreateLayeredChild<SD3D11LayeredPixelShaderCreationArgs>+0x78
0000001d`c9baf2f0 00007ffc`03720766 : 0000001d`c9dabc30 0000001d`c9d91fb0 00000000`00001718 00000000`00000000 : d3d11!CDevice::CreatePixelShader_Worker+0x1a0
0000001d`c9baf440 00007ff6`686e6700 : 00000001`00000000 00000000`00000000 ffffffff`fffffffe 0000001d`c9c74a60 : d3d11!CDevice::ID3D10Device1_CreatePixelShader_+0x26
0000001d`c9baf490 00007ff6`686e6634 : 00007ff6`686f2888 00000000`00008000 0000001d`c9dce1f0 00000000`0000021c : POC_EXEC_SHADER!FuzzFunction+0x40
0000001d`c9baf540 00007ff6`686e5caa : 0000001d`c9baf870 00007ff6`686e0000 0069005f`0000000a 00007ffb`00000000 : POC_EXEC_SHADER+0x6634
0000001d`c9baf830 00007ff6`686e7d62 : 00000000`0000000a 00000000`0000000a 00000000`00000000 00007ff6`67d7f000 : POC_EXEC_SHADER+0x5caa
0000001d`c9bafa70 00007ffc`06db13d2 : 00007ff6`686e7dd0 00000000`00000000 00000000`00000000 00000000`00000000 : POC_EXEC_SHADER!FuzzFunction+0x16a2
0000001d`c9bafab0 00007ffc`08a254f4 : 00007ffc`06db13b0 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x22
0000001d`c9bafae0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x34


THREAD_SHA1_HASH_MOD_FUNC:  817c6f72227ee987fefc30f98ceaf74ae31d6a27

THREAD_SHA1_HASH_MOD_FUNC_OFFSET:  29fa308109451b13e5a8204ec4cfbde54f8fd1f9

THREAD_SHA1_HASH_MOD:  221f28973e14c9cd059813826a888982f6ef78fc

FOLLOWUP_IP: 
igdusc64!USC::CShaderInputDecl::GetVertexIDRegisterNum+cb69
00007ffc`012dea29 488bce          mov     rcx,rsi

FAULT_INSTR_CODE:  e8ce8b48

SYMBOL_STACK_INDEX:  4

SYMBOL_NAME:  igdusc64!USC::CShaderInputDecl::GetVertexIDRegisterNum+cb69

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: igdusc64

IMAGE_NAME:  igdusc64.dll

DEBUG_FLR_IMAGE_TIMESTAMP:  5a32f1cc

STACK_COMMAND:  dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; ~0s ; kb

BUCKET_ID:  FAIL_FAST_INVALID_ARG_FAILURE_EXPLOITABLE_igdusc64!USC::CShaderInputDecl::GetVertexIDRegisterNum+cb69

FAILURE_EXCEPTION_CODE:  c0000409

FAILURE_IMAGE_NAME:  igdusc64.dll

BUCKET_ID_IMAGE_STR:  igdusc64.dll

FAILURE_MODULE_NAME:  igdusc64

BUCKET_ID_MODULE_STR:  igdusc64

FAILURE_FUNCTION_NAME:  USC::CShaderInputDecl::GetVertexIDRegisterNum

BUCKET_ID_FUNCTION_STR:  USC::CShaderInputDecl::GetVertexIDRegisterNum

BUCKET_ID_OFFSET:  cb69

BUCKET_ID_MODTIMEDATESTAMP:  5a32f1cc

BUCKET_ID_MODCHECKSUM:  5fd23b

BUCKET_ID_MODVER_STR:  10.18.14.4889

BUCKET_ID_PREFIX_STR:  FAIL_FAST_INVALID_ARG_FAILURE_EXPLOITABLE_

FAILURE_PROBLEM_CLASS:  FAIL_FAST

FAILURE_SYMBOL_NAME:  igdusc64.dll!USC::CShaderInputDecl::GetVertexIDRegisterNum

FAILURE_BUCKET_ID:  FAIL_FAST_INVALID_ARG_FAILURE_EXPLOITABLE_c0000409_igdusc64.dll!USC::CShaderInputDecl::GetVertexIDRegisterNum

TARGET_TIME:  2018-03-21T12:30:46.000Z

OSBUILD:  9600

OSSERVICEPACK:  17415

SERVICEPACK_NUMBER: 0

OS_REVISION: 0

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 8.1

OSEDITION:  Windows 8.1 WinNt SingleUserTS

USER_LCID:  0

OSBUILD_TIMESTAMP:  2014-10-29 03:45:30

BUILDDATESTAMP_STR:  141028-1500

BUILDLAB_STR:  winblue_r4

BUILDOSVER_STR:  6.3.9600.17415

ANALYSIS_SESSION_ELAPSED_TIME:  3e6e

ANALYSIS_SOURCE:  UM

FAILURE_ID_HASH_STRING:  um:fail_fast_invalid_arg_failure_exploitable_c0000409_igdusc64.dll!usc::cshaderinputdecl::getvertexidregisternum

FAILURE_ID_HASH:  {7f9c49a1-193c-e6e4-cca8-012bb2329742}

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

Timeline

2018-04-19 - Vendor Disclosure
2018-10-09 - Public Release

Credit

Discovered by Piotr Bania of Cisco Talos.