CVE-2021-33760

3 minute read

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

CVE-2021-33760

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.

Categories:

Updated: