CVE: CVE-2021-34503
Tested Versions:
- mfsrcsnk.dll 10.0.18362.836
Product URL(s):
Description of the vulnerability
There is a type confusion when parsing Quick Time video file format’s metadata that leads to OOB access on heap memory. The vulnerability can be triggered by navigating into folder contains POC
file, inside Internet Explorer and Microsoft Edge.
The crashes happens inside mfmp4srcsnk.dll
when parsing CQTSampleDescriptionAtom
. Stack trace.
(2154.3bf0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=05d90ee8 ebx=05d7ef00 ecx=05d84f78 edx=05d8efe8 esi=5ba00cf0 edi=05d80f00
eip=5ba43c64 esp=006fedec ebp=006fedf8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
mfmp4srcsnk!CAVCVideoSampleDescription::IsBetterForMediaType+0x44:
5ba43c64 8bb704010000 mov esi,dword ptr [edi+104h] ds:002b:05d81004=????????
0:000> k
# ChildEBP RetAddr
00 006fedf8 5b9fea8a mfmp4srcsnk!CAVCVideoSampleDescription::IsBetterForMediaType+0x44
01 006fee44 5b9fdc50 mfmp4srcsnk!CQTSampleDescriptionAtom::FinalParseAtom+0x36a
02 006feedc 5b9ff7bd mfmp4srcsnk!CQTSampleTable::FinalParseAtom+0x3d0
03 006fef6c 5b9ff51e mfmp4srcsnk!CQTAtom::FinalParseAtom+0xdd
04 006fef8c 5b9ff7bd mfmp4srcsnk!CQTMedia::FinalParseAtom+0x3e
05 006fefd4 5b9fecbc mfmp4srcsnk!CQTAtom::FinalParseAtom+0xdd
06 006ff004 5b9ff7bd mfmp4srcsnk!CQTTrack::FinalParseAtom+0x9c
07 006ff04c 5b9fd1e8 mfmp4srcsnk!CQTAtom::FinalParseAtom+0xdd
08 006ff094 5ba02ed9 mfmp4srcsnk!CQTMovie::FinalParseAtom+0x138
09 006ff0f8 5ba1e00c mfmp4srcsnk!CQTMovie::CreateQTMovie+0x2b9
0a 006ff180 5ba1d4bf mfmp4srcsnk!CQTMovie::CreateMovieFromBuffer+0x571
0b 006ff1b0 5ba252ff mfmp4srcsnk!MFCreateQTMovie+0x4a
0c 006ff1e8 5ba30cea mfmp4srcsnk!CMFMP4PropertyHandler::LoadMetadataProvider+0x13e
0d 006ff25c 5ba351cf mfmp4srcsnk!CMFMP4PropertyHandler::InternalInitialize+0xba
0e 006ff280 753fab92 mfmp4srcsnk!CMFPropHandlerBase::Initialize+0x1af
0f 006ff2d4 75480a38 windows_storage!InitializeFileHandlerWithStream+0x184
10 006ff364 754ef088 windows_storage!CFileSysItemString::HandlerCreateInstance+0x1ba
11 006ff3b4 753fd557 windows_storage!CFileSysItemString::_PropertyHandlerCreateInstance+0x69
12 006ff488 753fb4b6 windows_storage!CFileSysItemString::LoadHandler+0x181
13 006ff748 753fb0cc windows_storage!CFSFolder::LoadHandler+0xa6
14 006ff7a0 753f9849 windows_storage!CFSPropertyStoreFactory::_GetFileStore+0x148
15 006ff7b8 7545a37e windows_storage!CFSPropertyStoreFactory::_s_GetFileStore+0x19
16 006ff828 7545a094 windows_storage!CFSPropertyStoreFactory::_GetMultiplexPropertyStore+0x217
17 006ff86c 7545aa5e windows_storage!CFSPropertyStoreFactory::_GetPropertyStore+0xa9
18 006ff888 7544c632 windows_storage!CFSPropertyStoreFactory::GetPropertyStore+0x1e
19 006ffb7c 7544d5d6 windows_storage!CShellItem::_GetPropertyStoreWorker+0xb22
1a 006ffde4 76887ca6 windows_storage!CShellItem::GetPropertyStore+0xb6
*** WARNING: Unable to verify checksum for metadata.exe
1b 006ffe14 00021085 SHELL32!SHGetPropertyStoreFromParsingName+0x56
1c 006ffe74 00021190 metadata!target_func+0x35 [c:\users\bit\source\repos\mf\metadata\metadata.cpp @ 15]
1d 006ffe8c 0002137a metadata!wmain+0x40 [c:\users\bit\source\repos\mf\metadata\metadata.cpp @ 55]
1e (Inline) -------- metadata!invoke_main+0x1c [d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 90]
1f 006ffed4 77266359 metadata!__scrt_common_main_seh+0xfa [d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
20 006ffee4 77a97c24 KERNEL32!BaseThreadInitThunk+0x19
21 006fff40 77a97bf4 ntdll!__RtlUserThreadStart+0x2f
22 006fff50 00000000 ntdll!_RtlUserThreadStart+0x1b
@edi
points to an object of size only 0x100
but the code tries to access a property at offset 0x104
.
0:000> !heap -p -a @edi
address 05d80f00 found in
_DPH_HEAP_ROOT @ 5cc1000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
5cc25b0: 5d80f00 100 - 5d80000 2000
mfmp4srcsnk!CQTVideoSampleDescription::`vftable'
5bbfab70 verifier!AVrfDebugPageHeapAllocate+0x00000240
77b1909b ntdll!RtlDebugAllocateHeap+0x00000039
77a6bbad ntdll!RtlpAllocateHeap+0x000000ed
77a6b0cf ntdll!RtlpAllocateHeapInternal+0x0000022f
77a6ae8e ntdll!RtlAllocateHeap+0x0000003e
75d97610 msvcrt!malloc+0x00000090
5ba408cc mfmp4srcsnk!operator new+0x0000001d
5ba404ef mfmp4srcsnk!CQTVideoSampleDescription::Create+0x0000000a
5ba04947 mfmp4srcsnk!CQTSampleDescriptionAtom::CreateChildAtom+0x00000247
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba058a4 mfmp4srcsnk!CQTSampleDescriptionAtom::ParseAtom+0x000001b4
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba0a60e mfmp4srcsnk!CQTSampleTable::CreateChildAtom+0x0000037e
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba09972 mfmp4srcsnk!CQTMediaInformationAtom::CreateChildAtom+0x000003c2
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba09204 mfmp4srcsnk!CQTMedia::CreateChildAtom+0x000001e4
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba08a40 mfmp4srcsnk!CQTTrack::CreateChildAtom+0x00000950
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
0:000>
address 05d80f00 found in
_DPH_HEAP_ROOT @ 5cc1000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
5cc25b0: 5d80f00 100 - 5d80000 2000
mfmp4srcsnk!CQTVideoSampleDescription::`vftable'
5bbfab70 verifier!AVrfDebugPageHeapAllocate+0x00000240
77b1909b ntdll!RtlDebugAllocateHeap+0x00000039
77a6bbad ntdll!RtlpAllocateHeap+0x000000ed
77a6b0cf ntdll!RtlpAllocateHeapInternal+0x0000022f
77a6ae8e ntdll!RtlAllocateHeap+0x0000003e
75d97610 msvcrt!malloc+0x00000090
5ba408cc mfmp4srcsnk!operator new+0x0000001d
5ba404ef mfmp4srcsnk!CQTVideoSampleDescription::Create+0x0000000a
5ba04947 mfmp4srcsnk!CQTSampleDescriptionAtom::CreateChildAtom+0x00000247
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba058a4 mfmp4srcsnk!CQTSampleDescriptionAtom::ParseAtom+0x000001b4
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba0a60e mfmp4srcsnk!CQTSampleTable::CreateChildAtom+0x0000037e
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba09972 mfmp4srcsnk!CQTMediaInformationAtom::CreateChildAtom+0x000003c2
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba09204 mfmp4srcsnk!CQTMedia::CreateChildAtom+0x000001e4
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
5ba0af4e mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000035e
5ba08a40 mfmp4srcsnk!CQTTrack::CreateChildAtom+0x00000950
5ba0b197 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000077
5ba0ab4c mfmp4srcsnk!CQTAtom::ScanChildren+0x0000016c
5ba0c4ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
If there are more than one object the array and CQTSampleDescriptionAtom::CheckIfMultipleSampleEntriesAreAllowed
return True
iCQTSampleDescriptionAtom::FinalParseAtom
will loop through an array of objects and call the vftable’s function at offset 0xb8
. CQTSampleDescriptionAtom::CheckIfMultipleSampleEntriesAreAllowed
need to check if all object in the array is of the same type but it fails to do so. This lead to a type confusion.
v1 = CQTAtom::FinalParseAtom((CQTAtom *)this);
if ( v1 >= 0 )
{
v16 = this->length;
if ( v16 )
{
if ( v16 <= 1 || (v1 = CQTSampleDescriptionAtom::CheckIfMultipleSampleEntriesAreAllowed(this), v1 >= 0) )
{
this->a38 = 1;
if ( this->length > 0 )
{
while ( 1 )
{
wil::details::FeatureImpl<__WilFeatureTraits_Feature_MPEG4MultiSampleDescription>::ReportUsage(
v26,
v27,
v28);
if ( v4 )
{
v19 = (*(int (__thiscall **)(_DWORD, void *, void *))(*(_DWORD *)this->Array[v4] + 0xB8))(
*(_DWORD *)(*(_DWORD *)this->Array[v4] + 0xB8),
this->Array[v4],
this->Array[this->a38 - 1]);
v4 = v31;
if ( v19 )
this->a38 = v31 + 1;
}
v20 = (char *)this->Array[v4] + 12;
if ( (*(int (__thiscall **)(_DWORD, char *))(*(_DWORD *)v20 + 12))(*(_DWORD *)(*(_DWORD *)v20 + 12), v20) == 'drms' )
break;
v4 = v31 + 1;
v31 = v4;
if ( v4 >= this->length )
goto LABEL_57;
}
v1 = 0xC00D3700;
if ( !CallStackTracing::s_wpInstance )
CallStackTracing::InitInstance();
if ( *(_BYTE *)(CallStackTracing::s_wpInstance + 4) )
{
v21 = CallStackTracing::Context((CallStackTracing *)CallStackTracing::s_wpInstance);
CallStackContext::SetResult(v21, "CQTSampleDescriptionAtom::FinalParseAtom", 10986, 0xC00D3700);
}
if ( g_wppLevels >= 1u )
{
v3 = 792;
goto LABEL_56;
}
}
}
The type confusion occurs due to malformed header related to Protected Sample Entry Box structure
.
POC
Original files
The bytes in yellow are related to the crash. The fuzzer mutate encv
to ench
which causes the crash.
Timeline
- 2021-02-27 Reported to Vendor
- 2021-06-16 Vendor assign CVE