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