Talos Vulnerability Report

TALOS-2024-2008

Microsoft High Definition Audio Bus Driver HDAudBus_DMA multiple irp complete requests vulnerability

September 12, 2024
CVE Number

CVE-2024-45383

SUMMARY

A mishandling of IRP requests vulnerability exists in the HDAudBus_DMA interface of Microsoft High Definition Audio Bus Driver 10.0.19041.3636 (WinBuild.160101.0800). A specially crafted application can issue multiple IRP Complete requests which leads to a local denial-of-service. An attacker can execute malicious script/application to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Microsoft HDAudBus.sys 10.0.19041.3636 (WinBuild.160101.0800)

PRODUCT URLS

HDAudBus.sys - https://www.microsoft.com

CVSSv3 SCORE

5.0 - CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H

CWE

CWE-664 - Improper Control of a Resource Through its Lifetime

DETAILS

The High Definition Audio Bus Driver (hdaudbus.sys) is a Microsoft system driver responsible for managing and facilitating communication between the operating system and audio hardware that conforms to the Intel High Definition Audio (HD Audio) specification. This driver plays a crucial role in ensuring the proper functioning of audio devices on Windows systems, particularly those integrated into motherboards or connected via HD Audio interfaces.

There is a “multiple irp complete requests” vulnerability in HDAudBus.sys driver related to HDAudBus_DMA interface. Any user trying to obtain a handle via WmiOpenBlock to WMI HDAudBus_DMA block (represented by {AEF818D8-0878-4FB2-A776-536883B37AA1} GUID) with WMIGUID_NOTIFICATION flag set will cause a BSOD due to the invalid handling of the IRP package by the HDAudBus driver.

When we try to obtain an handle to the HDAudBus_DMA interface we land in the following function in HDAudBus.sys driver.

Line 1 	__int64 __fastcall HDAudBusWmiSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Line 2 	{
Line 3 	  int Status; // edi
Line 4 	  WDFDEVICE v5; // rbp
Line 5 	  struct _IO_STACK_LOCATION *CurrentStackLocation; // rax
Line 6 	  UCHAR MinorFunction; // cl
Line 7 	  struct _DEVICE_OBJECT *v8; // rax
Line 8 	  int v9; // edx
Line 9 	  PVOID userData; // rax
Line 10	  struct _WMILIB_CONTEXT *wmilibContext; // rcx
Line 11	  int error_code; // eax
Line 12	  enum _SYSCTL_IRP_DISPOSITION IrpDisposition; // [rsp+40h] [rbp+8h] BYREF
Line 13
Line 14	  IrpDisposition = IrpProcessed;
Line 15	  Status = Irp->IoStatus.Status;
Line 16	  v5 = WdfFunctions->pfnWdfWdmDeviceGetWdfDeviceHandle(WdfDriverGlobals, DeviceObject);
Line 17	  CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
Line 18	  MinorFunction = CurrentStackLocation->MinorFunction;
Line 19	  if ( MinorFunction <= (unsigned int)IRP_MN_EXECUTE_METHOD || MinorFunction == IRP_MN_REGINFO_EX )
Line 20	  {
Line 21		userData = WdfFunctions->pfnWdfObjectGetTypedContextWorker(WdfDriverGlobals, v5, off_FFFFF80131CF7090);
Line 22		if ( userData )
Line 23		{
Line 24		  wmilibContext = (struct _WMILIB_CONTEXT *)*((_QWORD *)userData + 21);
Line 25		  if ( wmilibContext )
Line 26		  {
Line 27			error_code = WmiSystemControl(wmilibContext, DeviceObject, Irp, &IrpDisposition);
Line 28			Status = error_code;
Line 29			if ( error_code >= 0 )
Line 30			{
Line 31			  if ( IrpDisposition == IrpProcessed )
Line 32				goto LABEL_16;
Line 33			  if ( IrpDisposition != IrpNotCompleted )
Line 34			  {
Line 35				++Irp->CurrentLocation;
Line 36				++Irp->Tail.Overlay.CurrentStackLocation;
Line 37				goto LABEL_6;
Line 38			  }
Line 39			  Irp->IoStatus.Status = error_code;
Line 40			}
Line 41	LABEL_15:
Line 42			IofCompleteRequest(Irp, 0);
Line 43			goto LABEL_16;
Line 44		  }
Line 45		}
Line 46	LABEL_14:
Line 47		Irp->IoStatus.Status = Status;
Line 48		goto LABEL_15;
Line 49	  }
Line 50
Line 51	LABEL_6:
Line 52	  v8 = WdfFunctions->pfnWdfDeviceWdmGetAttachedDevice(WdfDriverGlobals, v5);
Line 53	  Status = IofCallDriver(v8, Irp);
Line 54	LABEL_16:
Line 55
Line 56	  return (unsigned int)Status;
Line 57	}

Entering this function MinorFunction is set to:

IRP_MN_ENABLE_EVENTS - 0x04

Reaching line 27 , WmiSystemControl is called and execution flow is redirect to HDAudBusWmiFunctionControl.

Line 1 	NTSTATUS __fastcall HDAudBusWmiFunctionControl(
Line 2 			PDEVICE_OBJECT DeviceObject,
Line 3 			PIRP Irp,
Line 4 			int GuidIndex,
Line 5 			enum _WMIENABLEDISABLECONTROL Function,
Line 6 			unsigned __int8 Enable)
Line 7 	{
Line 8 	  struct _IO_STACK_LOCATION *CurrentStackLocation; // rax
Line 9 	  NTSTATUS error_status; // r8d
Line 10	  _QWORD *buffer; // rdx
Line 11
Line 12	  CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
Line 13	  error_status = 0;
Line 14	  if ( CurrentStackLocation->Parameters.WMI.BufferSize >= 0x30 )
Line 15	  {
Line 16		buffer = CurrentStackLocation->Parameters.WMI.Buffer;
Line 17		if ( Function )
Line 18		{
Line 19		  error_status = 0xC0000010;
Line 20		}
Line 21		else if ( GuidIndex )
Line 22		{
Line 23		  error_status = 0xC0000295;
Line 24		}
Line 25	  }
Line 26	  else
Line 27	  {
Line 28		error_status = 0xC0000023;
Line 29	  }
Line 30	  Irp->IoStatus.Status = error_status;
Line 31	  return WmiCompleteRequest(DeviceObject, Irp, error_status, 0, 0);
Line 32	}

Here, a few arguments are important : Function is set to 0, so condition at line 17 is false GuidIndex is equal 2 becase when we dump WMILIB_CONTEXT structure

Dump of WMILIB_CONTEXT

2: kd> dd rcx L1
ffffdd0f`511f4990  00000003

We can see that there are 3 GUIDs entries. Dumping informations about each entry of WMIGUIDREGINFO :

2: kd> dq fffff800`39bd5110
fffff800`39bd5110  fffff800`39bd3060 00081000`00000000
fffff800`39bd5120  fffff800`39bd2370 00000040`00000001
fffff800`39bd5130  fffff800`39bd2360 00000040`00000001

2: kd> dt nt!_GUID fffff800`39bd3060
 {9502cbc6-aa74-4eff-ba91-d9329bcce758}
   +0x000 Data1            : 0x9502cbc6
   +0x004 Data2            : 0xaa74
   +0x006 Data3            : 0x4eff
   +0x008 Data4            : [8]  "???"

2: kd> dt nt!_GUID fffff800`39bd2370
 {e7ad130f-d1e6-4969-ab89-7d78bce3a3fe}
   +0x000 Data1            : 0xe7ad130f
   +0x004 Data2            : 0xd1e6
   +0x006 Data3            : 0x4969
   +0x008 Data4            : [8]  "???"

2: kd> dt nt!_GUID fffff800`39bd2360
 {aef818d8-0878-4fb2-a776-536883b37aa1}
   +0x000 Data1            : 0xaef818d8
   +0x004 Data2            : 0x878
   +0x006 Data3            : 0x4fb2
   +0x008 Data4            : [8]  "???"

We can see previously mentioned GUID : {aef818d8-0878-4fb2-a776-536883b37aa1} is at index 2.

As we can see at lines 21-23 if GuidIndex is different than 0, error_status is set to 0xC0000295

// The guid passed was not recognized as valid by a WMI data provider.
//
#define STATUS_WMI_GUID_NOT_FOUND        ((NTSTATUS)0xC0000295L)

and what is the most imporant , at the end of this function, WmiCompleteRequest is called. After that we return to HDAudBusWmiSystemControl. Doing signed comparison operation at line 29

Line 29			if ( error_code >= 0 )

We do not meet the requirment, because 0xC0000295 ( 32bit) is below zero and code at line 42 is executed:

Line 42			IofCompleteRequest(Irp, 0);

Executing IofCompleteRequest is root cause of further problems with multiple irp complete requests, because according to the documentation IofCompleteRequest function should be called only when :

Line 27			error_code = WmiSystemControl(wmilibContext, DeviceObject, Irp, &IrpDisposition);

IrpDisposition after call to WmiSystemControl is set to IrpNotCompleted, in our case is set to IrpProcessed.

MSDN documentation

    IrpNotCompleted
    The IRP was processed but not completed, either because WMI detected an error and set up the IRP with an appropriate error code, or processed an IRP_MN_REGINFO or IRP_MN_REGINFO_EX request. 
    The driver must complete the IRP by calling IoCompleteRequest.    

Finishing execution of HDAudBusWmiSystemControl returns control back to the kernel, where there is a call attempting to free resources related to this IRP:

 IoFreeIrp(Irp);

This function detects that there are multiple irp complete requests which in turn results in Blue Screen of Death and denial of service.

Crash Information

For analysis of this file, run !analyze -v
nt!KeBugCheckEx:
fffff800`48ffcd70 48894c2408      mov     qword ptr [rsp+8],rcx ss:0018:ffffc882`d1e84240=0000000000000044
13: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

MULTIPLE_IRP_COMPLETE_REQUESTS (44)
A driver has requested that an IRP be completed (IoCompleteRequest()), but
the packet has already been completed.  This is a tough bug to find because
the easiest case, a driver actually attempted to complete its own packet
twice, is generally not what happened.  Rather, two separate drivers each
believe that they own the packet, and each attempts to complete it.  The
first actually works, and the second fails.  Tracking down which drivers
in the system actually did this is difficult, generally because the trails
of the first driver have been covered by the second.  However, the driver
stack for the current request can be found by examining the DeviceObject
fields in each of the stack locations.
Arguments:
Arg1: ffffcd81648605e0, Address of the IRP
Arg2: 0000000000002980
Arg3: 0000000000000000
Arg4: 0000000000000000

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


KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.mSec
    Value: 3592

    Key  : Analysis.Elapsed.mSec
    Value: 3638

    Key  : Analysis.IO.Other.Mb
    Value: 0

    Key  : Analysis.IO.Read.Mb
    Value: 0

    Key  : Analysis.IO.Write.Mb
    Value: 0

    Key  : Analysis.Init.CPU.mSec
    Value: 1546

    Key  : Analysis.Init.Elapsed.mSec
    Value: 10737

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 105

    Key  : Bugcheck.Code.KiBugCheckData
    Value: 0x44

    Key  : Bugcheck.Code.LegacyAPI
    Value: 0x44

    Key  : Bugcheck.Code.TargetModel
    Value: 0x44

    Key  : Failure.Bucket
    Value: 0x44_nt!WmipSendWmiIrp

    Key  : Failure.Hash
    Value: {48cfcddd-a58b-91ab-1333-f9836e1f36ce}

    Key  : Hypervisor.Enlightenments.Value
    Value: 68673420

    Key  : Hypervisor.Enlightenments.ValueHex
    Value: 417df8c

    Key  : Hypervisor.Flags.AnyHypervisorPresent
    Value: 1

    Key  : Hypervisor.Flags.ApicEnlightened
    Value: 0

    Key  : Hypervisor.Flags.ApicVirtualizationAvailable
    Value: 1

    Key  : Hypervisor.Flags.AsyncMemoryHint
    Value: 0

    Key  : Hypervisor.Flags.CoreSchedulerRequested
    Value: 0

    Key  : Hypervisor.Flags.CpuManager
    Value: 1

    Key  : Hypervisor.Flags.DeprecateAutoEoi
    Value: 1

    Key  : Hypervisor.Flags.DynamicCpuDisabled
    Value: 1

    Key  : Hypervisor.Flags.Epf
    Value: 0

    Key  : Hypervisor.Flags.ExtendedProcessorMasks
    Value: 1

    Key  : Hypervisor.Flags.HardwareMbecAvailable
    Value: 0

    Key  : Hypervisor.Flags.MaxBankNumber
    Value: 0

    Key  : Hypervisor.Flags.MemoryZeroingControl
    Value: 0

    Key  : Hypervisor.Flags.NoExtendedRangeFlush
    Value: 0

    Key  : Hypervisor.Flags.NoNonArchCoreSharing
    Value: 1

    Key  : Hypervisor.Flags.Phase0InitDone
    Value: 1

    Key  : Hypervisor.Flags.PowerSchedulerQos
    Value: 0

    Key  : Hypervisor.Flags.RootScheduler
    Value: 0

    Key  : Hypervisor.Flags.SynicAvailable
    Value: 1

    Key  : Hypervisor.Flags.UseQpcBias
    Value: 0

    Key  : Hypervisor.Flags.Value
    Value: 21500158

    Key  : Hypervisor.Flags.ValueHex
    Value: 14810fe

    Key  : Hypervisor.Flags.VpAssistPage
    Value: 1

    Key  : Hypervisor.Flags.VsmAvailable
    Value: 1

    Key  : Hypervisor.RootFlags.AccessStats
    Value: 1

    Key  : Hypervisor.RootFlags.CrashdumpEnlightened
    Value: 1

    Key  : Hypervisor.RootFlags.CreateVirtualProcessor
    Value: 1

    Key  : Hypervisor.RootFlags.DisableHyperthreading
    Value: 0

    Key  : Hypervisor.RootFlags.HostTimelineSync
    Value: 1

    Key  : Hypervisor.RootFlags.HypervisorDebuggingEnabled
    Value: 0

    Key  : Hypervisor.RootFlags.IsHyperV
    Value: 1

    Key  : Hypervisor.RootFlags.LivedumpEnlightened
    Value: 1

    Key  : Hypervisor.RootFlags.MapDeviceInterrupt
    Value: 1

    Key  : Hypervisor.RootFlags.MceEnlightened
    Value: 1

    Key  : Hypervisor.RootFlags.Nested
    Value: 0

    Key  : Hypervisor.RootFlags.StartLogicalProcessor
    Value: 1

    Key  : Hypervisor.RootFlags.Value
    Value: 1015

    Key  : Hypervisor.RootFlags.ValueHex
    Value: 3f7

    Key  : SecureKernel.HalpHvciEnabled
    Value: 0

    Key  : WER.OS.Branch
    Value: vb_release

    Key  : WER.OS.Version
    Value: 10.0.19041.1


BUGCHECK_CODE:  44

BUGCHECK_P1: ffffcd81648605e0

BUGCHECK_P2: 2980

BUGCHECK_P3: 0

BUGCHECK_P4: 0

FILE_IN_CAB:  MEMORY.DMP

IRP_ADDRESS: ffffcd81648605e0

PROCESS_NAME:  TestWMI.exe

STACK_TEXT:  
ffffc882`d1e84238 fffff800`4902446e     : 00000000`00000044 ffffcd81`648605e0 00000000`00002980 00000000`00000000 : nt!KeBugCheckEx
ffffc882`d1e84240 fffff800`48e18233     : 00000000`0000004a ffffc882`d1e84370 ffffc882`d1e84348 00000000`00000004 : nt!IopFreeIrp+0x20c21e
ffffc882`d1e84280 fffff800`49336b82     : ffffcd81`648605e0 00000000`00000030 ffffc882`d1e84358 ffffc882`d1e84410 : nt!IoFreeIrp+0x13
ffffc882`d1e842b0 fffff800`4937bfe7     : ffff8e0d`f8629120 ffffc882`d1e84410 ffffc882`d1e84390 fffff800`491fdc1a : nt!WmipSendWmiIrp+0xb6
ffffc882`d1e84310 fffff800`492ddfaf     : fffff800`49819ea0 ffffcd81`8f27be10 ffff8e0d`f8609810 ffffcd81`8f27bd70 : nt!WmipSendEnableDisableRequest+0x187
ffffc882`d1e845e0 fffff800`492ddf18     : ffffcd81`8f27bd70 ffff8e0d`f8609810 00000000`00224101 ffffcd81`8f27be10 : nt!WmipSendEnableRequest+0x6f
ffffc882`d1e84610 fffff800`49241773     : ffffcd81`8f27bd70 ffffc882`d1e84701 00000000`00224140 0000005a`a73af300 : nt!WmipEnableCollectOrEvent+0xcc
ffffc882`d1e84650 fffff800`492ea9bc     : 00000000`00000000 ffffc882`d1e847b0 00000000`00000018 ffffcd81`35c02ec0 : nt!WmipOpenBlock+0x11b
ffffc882`d1e846b0 fffff800`48e10665     : 00000000`00000002 ffffcd81`97727f60 00000000`00000000 ffffcd81`845925e0 : nt!WmipIoControl+0x22c
ffffc882`d1e84800 fffff800`49200fec     : 00000000`00000002 00000000`00000000 ffffcd81`8145a430 ffffcd81`977f3080 : nt!IofCallDriver+0x55
ffffc882`d1e84840 fffff800`49200c41     : ffffcd81`84592f20 ffffc882`d1e84b80 00000000`00040005 ffffcd81`84592f20 : nt!IopSynchronousServiceTail+0x34c
ffffc882`d1e848e0 fffff800`491fffb6     : 00000000`00000001 00000000`00000160 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0xc71
ffffc882`d1e84a20 fffff800`490105f8     : ffffcd81`789fb080 0000005a`a73af1b8 ffffc882`d1e84aa8 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
ffffc882`d1e84a90 00007fff`be5acf34     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x28
0000005a`a73af228 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`be5acf34


SYMBOL_NAME:  nt!WmipSendWmiIrp+b6

MODULE_NAME: nt

IMAGE_NAME:  ntkrnlmp.exe

IMAGE_VERSION:  10.0.19041.3448

STACK_COMMAND:  .cxr; .ecxr ; kb

BUCKET_ID_FUNC_OFFSET:  b6

FAILURE_BUCKET_ID:  0x44_nt!WmipSendWmiIrp

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {48cfcddd-a58b-91ab-1333-f9836e1f36ce}

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

13: kd> kb
 # RetAddr               : Args to Child                                                           : Call Site
00 fffff800`4902446e     : 00000000`00000044 ffffcd81`648605e0 00000000`00002980 00000000`00000000 : nt!KeBugCheckEx
01 fffff800`48e18233     : 00000000`0000004a ffffc882`d1e84370 ffffc882`d1e84348 00000000`00000004 : nt!IopFreeIrp+0x20c21e
02 fffff800`49336b82     : ffffcd81`648605e0 00000000`00000030 ffffc882`d1e84358 ffffc882`d1e84410 : nt!IoFreeIrp+0x13
03 fffff800`4937bfe7     : ffff8e0d`f8629120 ffffc882`d1e84410 ffffc882`d1e84390 fffff800`491fdc1a : nt!WmipSendWmiIrp+0xb6
04 fffff800`492ddfaf     : fffff800`49819ea0 ffffcd81`8f27be10 ffff8e0d`f8609810 ffffcd81`8f27bd70 : nt!WmipSendEnableDisableRequest+0x187
05 fffff800`492ddf18     : ffffcd81`8f27bd70 ffff8e0d`f8609810 00000000`00224101 ffffcd81`8f27be10 : nt!WmipSendEnableRequest+0x6f
06 fffff800`49241773     : ffffcd81`8f27bd70 ffffc882`d1e84701 00000000`00224140 0000005a`a73af300 : nt!WmipEnableCollectOrEvent+0xcc
07 fffff800`492ea9bc     : 00000000`00000000 ffffc882`d1e847b0 00000000`00000018 ffffcd81`35c02ec0 : nt!WmipOpenBlock+0x11b
08 fffff800`48e10665     : 00000000`00000002 ffffcd81`97727f60 00000000`00000000 ffffcd81`845925e0 : nt!WmipIoControl+0x22c
09 fffff800`49200fec     : 00000000`00000002 00000000`00000000 ffffcd81`8145a430 ffffcd81`977f3080 : nt!IofCallDriver+0x55
0a fffff800`49200c41     : ffffcd81`84592f20 ffffc882`d1e84b80 00000000`00040005 ffffcd81`84592f20 : nt!IopSynchronousServiceTail+0x34c
0b fffff800`491fffb6     : 00000000`00000001 00000000`00000160 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0xc71
0c fffff800`490105f8     : ffffcd81`789fb080 0000005a`a73af1b8 ffffc882`d1e84aa8 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
0d 00007fff`be5acf34     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x28
0e 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`be5acf34
TIMELINE

2024-06-24 - Vendor Disclosure
2024-08-26 - Vendor response that moderate DoS do not meet their bug bar
2024-08-27 - Talos request for CVE
2024-08-28 - Vendor said they do not assign CVEs to moderate severity issues
2024-09-12 - Public release

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.