Summary

Product Microsoft DirectMusic
Vendor Microsoft
Severity High
Affected Versions Microsoft DirectMusic Core Services DLL (dmusic.dll) version 10.0.22000.1
Tested Versions Microsoft DirectMusic Core Services DLL (dmusic.dll) version 10.0.22000.1
CVE Identifier CVE-2022-44668

CVSS3.1 Scoring System

Base Score: 7.8 (High)
Vector String: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Metric Value
Attack Vector (AV) Local
Attack Complexity (AC) Low
Privileges Required (PR) None
User Interaction (UI) Required
Scope (S) Unchanged
Confidentiality (C) High
Integrity (I) High
Availability (A) High

Product Overview

Microsoft DirectMusic Core Services DLL is a dynamic link library (DLL) that is part of the DirectMusic component of the DirectX multimedia API for Windows operating systems. DirectMusic is a high-level music composition and playback system designed to simplify the process of creating and playing back music in Windows-based multimedia applications.

The DirectMusic Core Services DLL provides essential services for managing and playing back MIDI and digital audio data in DirectMusic applications. It contains functions for managing MIDI and audio devices, synthesizers, and sound cards, as well as for loading and playing back MIDI and audio data.

Vulnerability Description

A vulnerability has been found in the dmusic.dll library. This vulnerability can be used by an attacker to cause an integer overflow through a specifically crafted application. As a result, when a DLS file is loaded and parsed, a heap double free can occur in the IDirectMusicPort COM component.

An attacker can exploit this vulnerability to remotely execute code on the victim’s machine. Below is the crash context:

===========================================================
VERIFIER STOP 000000000000000F: pid 0x61A8: corrupted suffix pattern 

	00000206446F1000 : Heap handle
	0000020644E1B900 : Heap block
	00000000000006F4 : Block size
	0000020644E1BFF4 : corruption address
===========================================================
This verifier stop is not continuable. Process will be terminated 
when you use the `go' debugger command.
===========================================================

(61a8.5f44): Break instruction exception - code 80000003 (first chance)
verifier!VerifierCaptureContextAndReportStop+0x112:
00007ffb`2e07716a cc              int     3
0:000> k
 # Child-SP          RetAddr           Call Site
00 00000074`60afe160 00007ffb`2e0774ae verifier!VerifierCaptureContextAndReportStop+0x112
01 00000074`60afe720 00007ffb`2e075c69 verifier!VerifierStopMessage+0x2ee
02 00000074`60afe7d0 00007ffb`2e07413c verifier!AVrfpDphReportCorruptedBlock+0x2c5
03 00000074`60afe890 00007ffb`2e0745de verifier!AVrfpDphCheckPageHeapBlock+0x16c
04 00000074`60afe900 00007ffb`2e07462b verifier!AVrfpDphFindBusyMemory+0xca
05 00000074`60afe940 00007ffb`2e072f5d verifier!AVrfpDphFindBusyMemoryAndRemoveFromBusyList+0x2b
06 00000074`60afe970 00007ffb`ecfa4e21 verifier!AVrfDebugPageHeapFree+0x8d
07 00000074`60afe9d0 00007ffb`ecf5c768 ntdll!RtlDebugFreeHeap+0x45
08 00000074`60afea60 00007ffb`ecec81fe ntdll!RtlpFreeHeap+0x96bc8
09 00000074`60afebc0 00007ffb`ecec7551 ntdll!RtlpFreeHeapInternal+0x79e
0a 00000074`60afec80 00007ffb`ebb1c6ac ntdll!RtlFreeHeap+0x51
0b 00000074`60afecc0 00007ffb`a425a60e msvcrt!free+0x1c
0c 00000074`60afecf0 00007ffb`819c9f03 dmusic!FreeHandle+0x1e
0d 00000074`60afed20 00007ffb`819d4107 dmsynth!CInstManager::Unload+0x1e3
0e 00000074`60afed60 00007ffb`a425b4cf dmsynth!CUserModeSynth::Unload+0x57
0f 00000074`60afeda0 00007ffb`a4259651 dmusic!CDirectMusicSynthPort::Unload+0x17f
*** WARNING: Unable to verify checksum for dsmusic.exe
10 00000074`60afede0 00007ff7`2957144f dmusic!CDirectMusicPortDownload::UnloadP+0x121
11 (Inline Function) --------`-------- dsmusic!DownloadAndUnload+0x55 [E:\harness\dsmusic\dsmusic\Source.cpp @ 46] 
12 00000074`60afee30 00007ff7`29571750 dsmusic!wmain+0x3df [E:\harness\dsmusic\dsmusic\Source.cpp @ 96] 
13 (Inline Function) --------`-------- dsmusic!invoke_main+0x22 [d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 90] 
14 00000074`60aff700 00007ffb`ec3854e0 dsmusic!__scrt_common_main_seh+0x10c [d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 
15 00000074`60aff740 00007ffb`ecea485b KERNEL32!BaseThreadInitThunk+0x10
16 00000074`60aff770 00000000`00000000 ntdll!RtlUserThreadStart+0x2b
0:000> !heap -p -a 0000020644E1B900 
    address 0000020644e1b900 found in
    _DPH_HEAP_ROOT @ 206446f1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                             206447065b0:      20644e1b900              6f4 -      20644e1b000             2000
    00007ffbecfa400c ntdll!RtlDebugAllocateHeap+0x0000000000000048
    00007ffbecf5d750 ntdll!RtlpAllocateHeap+0x0000000000092780
    00007ffbecec910c ntdll!RtlpAllocateHeapInternal+0x00000000000006ac
    00007ffbebb1c750 msvcrt!malloc+0x0000000000000070
    00007ffba42584a4 dmusic!CDirectMusicPortDownload::AllocateBuffer+0x0000000000000044
    00007ffba42589c8 dmusic!CDirectMusicPortDownload::DownloadP+0x0000000000000468
    00007ffba425a5a7 dmusic!CDirectMusicSynthPort::DownloadInstrument+0x0000000000000047
    00007ff72957143d dsmusic!wmain+0x00000000000003cd [E:\harness\dsmusic\dsmusic\Source.cpp @ 96]
    00007ff729571750 dsmusic!__scrt_common_main_seh+0x000000000000010c [d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
    00007ffbec3854e0 KERNEL32!BaseThreadInitThunk+0x0000000000000010
    00007ffbecea485b ntdll!RtlUserThreadStart+0x000000000000002b

The vulnerability lies in the implementation of the following COM class:

  • Interface: IDirectMusicCollection (480FF4B0-28B2-11D1-BEF7-00C04FBF8FEF)
  • Interface: IDirectMusicPort
  • Server: C:\WINDOWS\System32\dmusic.dll

This COM class is a part of DirectMusic, which is a software module that allows for the loading and parsing of downloadable sound (DLS) files. DLS files contain different chunks and lists, such as Collection, Wave Pool, Wave File, List of Instrument, List of Region, List of Articulators, and others. The vulnerability can be observed in the dmusic.dll file.

CArticulation::Load(CRiffParser *)
CCollection::Load(IStream *)
CCopyright::Load(CRiffParser *)
CExtensionChunk::Load(CRiffParser *)
CConditionChunk::Load(CRiffParser *)
CInstrObj::Load(ulong,CRiffParser *,CCollection *)
CRegion::Load(CRiffParser *)
CWaveObj::Load(ulong,CRiffParser *,CCollection *)

Each chunk and list in the DLS file of dmusic.dll has its own unique structure. In this context, we will focus on the parsing of the List of Articulators.

To achieve this, we need to examine the function CDirectMusicSynthPort::Unload.

__int64 __fastcall CDirectMusicSynthPort::Unload(CDirectMusicSynthPort *this, CDownloadBuffer *pIDMDownload)
{
  ....
  if ( !pIDMDownload
    || !pIDMDownload->vftbl_0_000000018001B258
    || !pIDMDownload->vftbl_0_000000018001B258->CDownloadBuffer::QueryInterface )
  {
    return 2147500035i64;
  }
  ....
  ....
        ((void (__fastcall *)(CDownloadBuffer *))pIDMDownload->vftbl_0_000000018001B258->CDownloadBuffer::Release)(pIDMDownload); // [1]
        v7 = ((__int64 (__fastcall *)(IDirectMusicSynth *, HANDLE, __int64 (__fastcall *)(void *, void *), CDownloadBuffer *))this->m_pSynth->lpVtbl->Unload)( // [2]
               this->m_pSynth,
               pIDMDownload->m_DLHandle,
               FreeHandle,
               pIDMDownload);
      }
    }
  }
  LeaveCriticalSection(v5);
  return (unsigned int)v7;
}

When CDirectMusicSynthPort::Unload function is executed, it will free up the memory of CDownloadBuffer *pIDMDownload, which is commented at [1], by calling the CDownloadBuffer::Release function. Additionally, it will also call the dmsynth!CUserModeSynth::Unload function with the FreeHandle callback to free up the memory of CDownloadBuffer mentioned at [2].

To understand the first action better, let’s examine the CDownloadBuffer::Release function in detail.

__int64 __fastcall CDownloadBuffer::Release(CDownloadBuffer *this)
{
    unsigned __int32 v2; // edi

    v2 = _InterlockedDecrement(&this->m_cRef);
    if ( !v2 && this )
    {
        this->vftbl_0_000000018001B258 = (CDownloadBuffer_VTABLE_0_000000018001B258::vtable *)&CDownloadBuffer::`vftable'{for `IDirectMusicDownload'};
        this->vftbl_1_000000018001B278 = (CDownloadBuffer_VTABLE_8_000000018001B278::vtable *)&CDownloadBuffer::`vftable'{for `IDirectMusicDownloadPrivate'};
        free(this->m_pvBuffer); // free m_pvBuffer
        free(this);
    }
    return v2;
}

This code contains a function named FreeHandle which frees up the memory area m_pvBuffer used by the CDownloadBuffer class. The function is called by a callback mechanism. Here is the code for FreeHandle:

__int64 __fastcall FreeHandle(void *a1, CDownloadBuffer *a2)
{
    void *v2; // rcx
    v2 = a2->m_pvBuffer;
    a2->m_pvBuffer = 0i64;
    *(_QWORD *)&a2->m_dwHeaderSize = 0i64;
    free(v2); // free m_pvBuffer 1 more time
    CDownloadBuffer::Release(a2);
    return 0i64;
}

It is important to note that FreeHandle continues to free m_pvBuffer without checking if it is available. This can cause a double free bug.

Credits

Lê Hữu Quang Linh (@linhlhq) of of STAR Labs SG Pte. Ltd. (@starlabs_sg)

Timeline:

  • 2022-07-29 Vendor Disclosure
  • 2022-07-29 Initial Vendor Contact
  • 2022-12-13 Vendor Patch Release