CVE-2021-33760
Microsoft Media Foundation Information Disclosure Vulnerability (mfsrcsnk.dll)
Summary
A vulnerability is present in mfsrcsnk.dll
, which is part of the Microsoft Media Foundation framework. An integer underflow leads to an Out-of-Bounds (OOB) Read when parsing an MP3 frame header.
The vulnerability can be triggered by right-clicking on the file poc.mp3
in Windows Explorer with Page Heap enabled on explorer.exe
.
CVE Number
Tested Versions
Software | Version |
---|---|
Windows 10 - Media Foundation MP3 File Source DLL | 10.0.19041.1316 |
Technical Details
The crash occurs in mfsrcsnk.dll
:
0:000> g
(56c8.7dc4): Access violation - code c0000005 (first/second chance not available)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
Time Travel Position: B8573:0
mfsrcsnk!CMPEGFrame::DeSerializeFrameHeader+0x42:
00007ffb`2629f872 418b0e mov ecx,dword ptr [r14] ds:000001c7`29218504=????????
0:000> k
# Child-SP RetAddr Call Site
00 0000003f`dc7cde80 00007ffb`2629d50c mfsrcsnk!CMPEGFrame::DeSerializeFrameHeader+0x42
01 0000003f`dc7cdf00 00007ffb`2629cb58 mfsrcsnk!CMP3MediaSourcePlugin::ReadMPEGFrameHeader+0x78
02 0000003f`dc7cdf70 00007ffb`2629e8bc mfsrcsnk!CMP3MediaSourcePlugin::DoReadFrameHeader+0x5c
03 0000003f`dc7cdff0 00007ffb`2629f1fa mfsrcsnk!CMP3MediaSourcePlugin::ParseHeader+0x1cc
04 0000003f`dc7ce0d0 00007ffb`2629f060 mfsrcsnk!CMFMP3PropertyHandler::FeedNextBufferToPlugin+0x12e
05 0000003f`dc7ce170 00007ffb`262992e3 mfsrcsnk!CMFMP3PropertyHandler::FeedBuffersToPlugin+0x9c
06 0000003f`dc7ce230 00007ffb`262a9da4 mfsrcsnk!CMFMP3PropertyHandler::InternalInitialize+0x103
07 0000003f`dc7ce300 00007ffb`5f400df9 mfsrcsnk!CMFPropHandlerBase::Initialize+0x84
08 0000003f`dc7ce360 00007ffb`5f3fdcfb windows_storage!InitializeFileHandlerWithStream+0x175
09 0000003f`dc7ce420 00007ffb`5f43a345 windows_storage!CFileSysItemString::HandlerCreateInstance+0x2c7
0a 0000003f`dc7ce510 00007ffb`5f3de47a windows_storage!CFileSysItemString::_PropertyHandlerCreateInstance+0xad
0b 0000003f`dc7ce5c0 00007ffb`5f3ece20 windows_storage!CFileSysItemString::LoadHandler+0x1aa
0c 0000003f`dc7ce710 00007ffb`5f3c9d95 windows_storage!CFSFolder::LoadHandler+0xe0
0d 0000003f`dc7cea70 00007ffb`5f3caeca windows_storage!CFSPropertyStoreFactory::_GetFileStore+0x165
0e 0000003f`dc7ceb40 00007ffb`5f3cb042 windows_storage!CFSPropertyStoreFactory::_GetPropertyStore+0x20e
0f 0000003f`dc7cec30 00007ffb`5f3ca824 windows_storage!CFSPropertyStoreFactory::GetPropertyStore+0x22
10 0000003f`dc7cec70 00007ffb`5f3ca3cb windows_storage!CShellItem::_GetPropertyStoreWorker+0x384
11 0000003f`dc7cf1b0 00007ffb`5fd09e3b windows_storage!CShellItem::GetPropertyStore+0xdb
12 0000003f`dc7cf480 00007ff6`10d611ab SHELL32!SHGetPropertyStoreFromParsingName+0x5b
13 0000003f`dc7cf4f0 00007ff6`10d6111d harness!fuzzme+0x3b
14 0000003f`dc7cf540 00007ff6`10d615f4 harness!wmain+0x11d
15 0000003f`dc7cf7a0 00007ffb`611f7c24 harness!fuzzme+0x484
16 0000003f`dc7cf7e0 00007ffb`61aad721 KERNEL32!BaseThreadInitThunk+0x14
17 0000003f`dc7cf810 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:000> !heap -p -a @r14
address 000001c729218504 found in
_DPH_HEAP_ROOT @ 1c7290a1000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
1c7290a5d68: 1c729214000 4000 - 1c729213000 6000
00007ffb61b4462f ntdll!RtlDebugAllocateHeap+0x000000000000003f
00007ffb61af501e ntdll!RtlpAllocateHeap+0x0000000000078cce
00007ffb61a7b4bb ntdll!RtlpAllocateHeapInternal+0x0000000000000a1b
00007ffb60209da0 msvcrt!malloc+0x0000000000000070
00007ffb541aad4b MFPlat!operator new+0x0000000000000023
00007ffb541a1d76 MFPlat!MFCreateMemoryBuffer+0x0000000000000056
00007ffb2629f140 mfsrcsnk!CMFMP3PropertyHandler::FeedNextBufferToPlugin+0x0000000000000074
00007ffb2629f060 mfsrcsnk!CMFMP3PropertyHandler::FeedBuffersToPlugin+0x000000000000009c
00007ffb262992e3 mfsrcsnk!CMFMP3PropertyHandler::InternalInitialize+0x0000000000000103
00007ffb262a9da4 mfsrcsnk!CMFPropHandlerBase::Initialize+0x0000000000000084
00007ffb5f400df9 windows_storage!InitializeFileHandlerWithStream+0x0000000000000175
00007ffb5f3fdcfb windows_storage!CFileSysItemString::HandlerCreateInstance+0x00000000000002c7
00007ffb5f43a345 windows_storage!CFileSysItemString::_PropertyHandlerCreateInstance+0x00000000000000ad
00007ffb5f3de47a windows_storage!CFileSysItemString::LoadHandler+0x00000000000001aa
00007ffb5f3ece20 windows_storage!CFSFolder::LoadHandler+0x00000000000000e0
00007ffb5f3c9d95 windows_storage!CFSPropertyStoreFactory::_GetFileStore+0x0000000000000165
00007ffb5f3caeca windows_storage!CFSPropertyStoreFactory::_GetPropertyStore+0x000000000000020e
00007ffb5f3cb042 windows_storage!CFSPropertyStoreFactory::GetPropertyStore+0x0000000000000022
00007ffb5f3ca824 windows_storage!CShellItem::_GetPropertyStoreWorker+0x0000000000000384
00007ffb5f3ca3cb windows_storage!CShellItem::GetPropertyStore+0x00000000000000db
00007ffb5fd09e3b SHELL32!SHGetPropertyStoreFromParsingName+0x000000000000005b
00007ff610d611ab harness!fuzzme+0x000000000000003b
00007ff610d6111d harness!wmain+0x000000000000011d
00007ff610d615f4 harness!fuzzme+0x0000000000000484
00007ffb611f7c24 KERNEL32!BaseThreadInitThunk+0x0000000000000014
00007ffb61aad721 ntdll!RtlUserThreadStart+0x0000000000000021
As seen above, @r14
points to an invalid region on the heap.
Vulnerability Analysis
At CMP3MediaSourcePlugin::ParseHeader+0x314 (mfsrcsnk.dll+0xea04)
, the function CMP3MediaSourcePlugin::DoScanForFrameHeader()
is called. This stores the value 0x2282
into the variable offset
.
// buf = 0x000001c729214000, remaining_size = 0x00000000000022e6, &offset = 0x0000003fdc7ce060
hr = CMP3MediaSourcePlugin::DoScanForFrameHeader(MPEGFrame, buf, remaining_size, &offset);
At CMP3MediaSourcePlugin::ParseHeader+0x20e (mfsrcsnk.dll+0xe8fe)
the variables remaining_size
and buf
are updated.
LABEL_29:
LODWORD(v34) = offset;
remaining_size -= offset; // 0x00000000000022e6 - 0x0000000000002282 = 0x0000000000000064
buf += offset; // 0x000001c729214000 + 0x0000000000002282 = 0x000001c729216282
goto LABEL_30;
}
At CMP3MediaSourcePlugin::ParseHeader+0x2d9 (mfsrcsnk.dll+0xe9c9)
, the function CMP3MediaSourcePlugin::DoReadFirstFrameBody()
is called.
// buf=000001c729216282, remaining_size=0000000000000064, &offset=0000003fdc7ce060
hr = CMP3MediaSourcePlugin::DoReadFirstFrameBody(MPEGFrame, buf, remaining_size, &offset);
Eventually, the function CMPEGFrame::DeSerializeFrameBody()
is called with the same arguments:
0:000> k
# Child-SP RetAddr Call Site
00 0000003f`dc7cdee8 00007ffb`2629f789 mfsrcsnk!CMPEGFrame::DeSerializeFrameBody
01 0000003f`dc7cdef0 00007ffb`2629aaa1 mfsrcsnk!CMP3MediaSourcePlugin::ReadMPEGFrameBody+0x49
02 0000003f`dc7cdf60 00007ffb`2629e9ce mfsrcsnk!CMP3MediaSourcePlugin::DoReadFirstFrameBody+0x41
0:000> r rcx, rdx, r8, r9
rcx=000001c72921bea0 rdx=000001c729216282 r8=0000000000000064 r9=0000003fdc7ce060
At CMPEGFrame::DeSerializeFrameBody+0x2fe5f (mfsrcsnk.dll+0x3f15f)
, as remaining_size
is less than required_size
, the check fails and the function immediately returns with HRESULT 0
. The value of offset
is not updated and remains 0x2282
.
if ( body_tag == 'ofnI' ) {
LODWORD(required_size) = required_size + 0x74;
if ( remaining_size < required_size ) // required_size = 0x74
goto LABEL_22;
}
LABEL_22:
CallStackScopeTrace::~CallStackScopeTrace(v13);
return hr;
}
At CMP3MediaSourcePlugin::ParseHeader+0x2f7 (mfsrcsnk.dll+0xe9eb)
, the variables remaining_size
and buf
are updated again. However, as remaining_size
is an unsigned int
, an integer underflow occurs, causing remaining_size
to store a large value. Also, buf
now points to an invalid heap region.
LODWORD(v34) = offset;
remaining_size -= offset; // 0x0000000000000064 - 0x0000000000002282 = 0x00000000ffffdde2
buf += offset; // 0x000001c729216282 + 0x0000000000002282 = 000001c729218504
At CMPEGFrame::DeSerializeFrameHeader+0x39 (mfsrcsnk.dll+0xf869)
, a check is performed. Since remaining_size
contains a large value, the check is passed. Execution flow continues, causing an OOB Read and a crash when trying to access the invalid pointer stored in buf
.
if ( remaining_size < 4 ) {
... // Irrelevant Code
}
v10 = *buf; // OOB Read
Conclusion
This vulnerability could result in code execution when chained with other vulnerabilities.