Talos Vulnerability Report

TALOS-2020-1012

Microsoft Media Foundation CQTMetadataKeysAtom GetKeyForIndex Information Disclosure Vulnerability

April 14, 2020
CVE Number

CVE-2020-0939

Summary

An exploitable code execution vulnerability exists in the CQTMetadataKeysAtom GetKeyForIndex functionality of Microsoft Corporation Microsoft Media Foundation 10.0.18362.476. A specially crafted malformed file can cause code execution resulting in remote code execution. An attacker can provide a malicious file to trigger this vulnerability.

Tested Versions

Microsoft Corporation Microsoft Media Foundation 10.0.18362.476
Microsoft Corporation Windows Media Player 12.0.18362.449

Product URLs

https://docs.microsoft.com/pl-pl/windows/win32/medfound/microsoft-media-foundation-sdk

CVSSv3 Score

6.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N

CWE

CWE-125 - Out-of-bounds Read

Details

The Microsoft Media Foundation is a COM based multimedia framework available in Microsoft Windows since Windows Vista. It provides all sort of functionality related with audio/video operations.

This vulnerability is present in the Media Foundation MPEG4 dll which is part of the Microsoft Media Foundation framework.A specially crafted QuickTime can lead to aninformation disclosure vulnerability. Attaching a debugger to the Windows Media Player (with PageHeap turned on) and loading the malformed MOV file we end up in the following context:

(7b4.e798): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00879418 ebx=14778f98 ecx=14778f98 edx=1477af70 esi=000000a8 edi=00000000
eip=58bb3a12 esp=008793d8 ebp=008793e8 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202
mfmp4srcsnk!CQTMetadataKeysAtom::GetKeyForIndex+0x25:
58bb3a12 8b4c32e8        mov     ecx,dword ptr [edx+esi-18h] ds:002b:1477b000=????????
0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 008793e8 58bb889d 00000006 00879418 00879424 mfmp4srcsnk!CQTMetadataKeysAtom::GetKeyForIndex+0x25
01 0087943c 58b043cb 1477cec8 00000006 0000004b mfmp4srcsnk!CQTMetadataMapAtom::CreateChildAtom+0x7d
02 0087948c 58b042a8 152f0eed 00000008 000000e0 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0xbb
03 008794b8 58b053ad 1477cec8 58b052b0 1477cec8 mfmp4srcsnk!CQTAtom::ScanChildren+0xc8
04 008794d8 58b04b40 1477cec8 1477cec8 696c7374 mfmp4srcsnk!CQTAtom::ParseAtom+0xfd
05 008794fc 58b0d890 14774ff8 1477cec8 00879524 mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x1d0
06 00879540 58b043cb 14774f70 696c7374 000000e8 mfmp4srcsnk!CMP4MetadataAtom::CreateChildAtom+0x380
07 00879590 58b042a8 152f0d8d 00000008 00000240 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0xbb
08 008795bc 58b053ad 14774f70 14774f70 14774f70 mfmp4srcsnk!CQTAtom::ScanChildren+0xc8
09 008795dc 58b248a1 14774f70 58b24860 00000000 mfmp4srcsnk!CQTAtom::ParseAtom+0xfd
0a 008795f0 58b04a8b 14774f70 00000000 13f22f08 mfmp4srcsnk!CMP4MetadataAtom::ParseAtom+0x41
0b 00879614 58b0693e 13f22fac 14774f70 00879654 mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x11b
0c 00879710 58b04559 13f22f08 6d657461 00000248 mfmp4srcsnk!CQTMovie::CreateChildAtom+0x34e
0d 00879760 58b042a8 152f09e8 00000008 0000060f mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x249
0e 0087978c 58af5d78 13f22f08 00000000 681874b0 mfmp4srcsnk!CQTAtom::ScanChildren+0xc8
0f 008797c0 58af4124 13f20fe8 00000008 00000000 mfmp4srcsnk!CQTMovie::CreateQTMovie+0x98
10 008798c0 58af39a6 152eef98 00000008 00000000 mfmp4srcsnk!CQTMovie::CreateMovieFromBuffer+0x1c6
11 008798e8 58b19600 00000008 00000000 274629c0 mfmp4srcsnk!MFCreateQTMovie+0x30
12 00879920 58b13d9a 274629c0 58b13ce0 27360f58 mfmp4srcsnk!CMFMP4PropertyHandler::LoadMetadataProvider+0x13e
13 00879990 58b18782 00000040 00000000 58b18710 mfmp4srcsnk!CMFMP4PropertyHandler::InternalInitialize+0xba
14 008799b4 754e2884 274629c0 27360f58 00000040 mfmp4srcsnk!CMFPropHandlerBase::Initialize+0x72
15 00879a08 754dfd76 00879b40 0ebd4ef8 00000020 windows_storage!InitializeFileHandlerWithStream+0x184
16 00879a98 7550d9e8 00000004 00879b40 00879ae0 windows_storage!CFileSysItemString::HandlerCreateInstance+0x1ba
17 00879ae8 754e0a97 00000004 00879b40 5f26b8c7 windows_storage!CFileSysItemString::_PropertyHandlerCreateInstance+0x69
18 00879bbc 754c9c96 00000020 7537ae2c 00000000 windows_storage!CFileSysItemString::LoadHandler+0x181
19 00879e7c 754c94f0 196bbe84 29008e90 00000000 windows_storage!CFSFolder::LoadHandler+0xa6
1a 00879ed4 754ca709 00000000 00000000 7537ae18 windows_storage!CFSPropertyStoreFactory::_GetFileStore+0x148
1b 00879eec 75497d8e 13420fe0 00000000 00000000 windows_storage!CFSPropertyStoreFactory::_s_GetFileStore+0x19
1c 00879f5c 75497aa4 00000000 7537ae18 00000000 windows_storage!CFSPropertyStoreFactory::_GetMultiplexPropertyStore+0x217
1d 00879fa0 7549846e 00000000 7537ae18 00000000 windows_storage!CFSPropertyStoreFactory::_GetPropertyStore+0xa9
1e 00879fbc 7548a032 13420fe0 00000000 00000000 windows_storage!CFSPropertyStoreFactory::GetPropertyStore+0x1e
1f 0087a2b0 7548afd6 00000000 00000000 00000000 windows_storage!CShellItem::_GetPropertyStoreWorker+0xb22
20 0087a518 65df92d8 24788f8c 00000000 65cbad10 windows_storage!CShellItem::GetPropertyStore+0xb6
WARNING: Stack unwind information not available. Following frames may be wrong.
21 0087a7e8 65e5f037 1501ef38 65cbd9f8 64440492 wmp+0x1a92d8
22 0087a87c 65e63bf5 1501ef38 0087a894 65e63bc0 wmp!Ordinal3000+0x18ef7
23 0087a898 65da5810 15013fc8 0087a964 00000000 wmp!Ordinal3000+0x1dab5
24 0087a97c 66047da5 00000001 0087a9e4 0087a9bc wmp+0x155810
25 0087aa18 65f1af63 15068ff0 13da2c50 13da2bf0 wmp!Ordinal3002+0xe3115
26 0087aa80 65e2b194 08000000 00000009 13da2bf0 wmp!DllCanUnloadNow+0x9edf3
27 0087aaa0 65e2b1a5 08000000 00000006 0087ab08 wmp+0x1db194
28 0087aac4 6602a663 08000000 00000004 0087ab90 wmp+0x1db1a5
29 0087aaec 65fde4c3 13da2bf0 08000000 27231088 wmp!Ordinal3002+0xc59d3
2a 0087ab0c 766e7eff 13da2bc0 27231088 0087ab90 wmp!Ordinal3002+0x79833
2b 0087ab2c 766ca521 13da2bc0 00000060 00000004 OLEAUT32!DispCallFunc+0x16f
2c 0087adf0 766cb12c 0c738088 13da2bc0 000002ff OLEAUT32!CTypeInfo2::Invoke+0x631
2d 0087b0b4 766cb12c 0c7382f0 13da2bc0 000002ff OLEAUT32!CTypeInfo2::Invoke+0x123c
2e 0087b378 65d7f53e 0c738298 13da2bc0 000002ff OLEAUT32!CTypeInfo2::Invoke+0x123c
2f 0087b3a4 65bbfd02 13da2bc0 000002ff 65ba8e9c wmp+0x12f53e
30 0087b4d0 65bc26da 14cdad10 0087b52c 00000003 jscript!VAR::InvokeByName+0x452
31 0087b5d4 65bc5b7f 14cdad10 00000000 00000003 jscript!VAR::InvokeByDispID+0x13a
32 0087b7cc 65bc1c2e 00000000 14e12f88 0b7a0fd0 jscript!CScriptRuntime::Run+0x2dff
33 0087b8bc 65bc189e 00000000 00000001 0c571ed0 jscript!ScrFncObj::CallWithFrameOnStack+0x8e
34 0087b914 65bc22d6 00000000 00000001 0c571ed0 jscript!ScrFncObj::Call+0x7e
35 0087b9b4 65bc2635 14cdad10 0000005b 00000001 jscript!NameTbl::InvokeInternal+0x186
36 0087babc 65bc5c0e 14cdad10 00000000 00000001 jscript!VAR::InvokeByDispID+0x95
37 0087bcb4 65bc1c2e 00000000 14d8cf88 0b7a0fd0 jscript!CScriptRuntime::Run+0x2e8e
38 0087bda4 65bc189e 00000000 00000001 0c571f40 jscript!ScrFncObj::CallWithFrameOnStack+0x8e
39 0087bdfc 65bc22d6 00000000 00000001 0c571f40 jscript!ScrFncObj::Call+0x7e
3a 0087be9c 65bc2635 14cdad10 00000051 00000001 jscript!NameTbl::InvokeInternal+0x186
3b 0087bfa4 65bc5c0e 14cdad10 00000000 00000001 jscript!VAR::InvokeByDispID+0x95
3c 0087c19c 65bc1c2e 00000000 0e2b4f88 0b7a0fd0 jscript!CScriptRuntime::Run+0x2e8e
3d 0087c28c 65bc189e 00000000 00000001 0c571fc0 jscript!ScrFncObj::CallWithFrameOnStack+0x8e
3e 0087c2e4 65bca564 00000000 00000001 0c571fc0 jscript!ScrFncObj::Call+0x7e
3f 0087c3a0 65be49cd 0e2b4f88 00000000 00000001 jscript!CSession::Execute+0x314
40 0087c3f4 65e5260d 27354fc8 000013ed 65cb8614 jscript!CEventSink::Invoke+0x11d
41 0087c440 65fd849d 000013ed 0087c468 0795fd00 wmp!Ordinal3000+0xc4cd
42 0087c47c 65fb8e5f 00000009 65cc4aec 0795fd10 wmp!Ordinal3002+0x7380d
43 0087c4f4 65ebd207 00000009 0795fd00 00000008 wmp!Ordinal3002+0x541cf
44 0087c558 65d84873 00000015 00000001 0ba38ea0 wmp!DllCanUnloadNow+0x41097
45 0087c57c 65d847a3 00000009 00000000 0ba38ea0 wmp+0x134873
46 0087c5c4 6600056e 00000009 13da2bc0 65d5ce00 wmp+0x1347a3
47 0087c618 65ebc0bb 13da2bc0 00000005 00000000 wmp!Ordinal3002+0x9b8de
48 0087c6d8 65ffaa77 13da2bc0 00000001 00000001 wmp!DllCanUnloadNow+0x3ff4b
49 0087c700 65faa0ed 0ba38ea8 13da2bc0 0a276f50 wmp!Ordinal3002+0x95de7
4a 0087c73c 65fa9c55 13da2bc0 0795fd00 65fad3b0 wmp!Ordinal3002+0x4545d
4b 0087c794 65fad4e0 00000000 0795fd60 65fad3b0 wmp!Ordinal3002+0x44fc5
4c 0087c7d0 65fbf362 0a276f50 65fbf310 0795fd60 wmp!Ordinal3002+0x48850
4d 0087c7e8 661c4c18 00000003 6602ed90 14c7eda8 wmp!Ordinal3002+0x5a6d2
4e 0087c854 662c1897 00000000 14c7eda8 662c10e0 wmp!Ordinal3002+0x25ff88
4f 0087c9d0 662a6c2a 1dd02fe0 002c13aa 00000003 wmp!Ordinal3002+0x35cc07
50 0087ca28 662a5ada 14c74930 1dd02fe0 00000000 wmp!Ordinal3002+0x341f9a
51 0087ca58 74b20ed2 14c7afe4 1dd02fe0 00000000 wmp!Ordinal3002+0x340e4a
52 0087ca98 7662f4d4 11c4bfe0 00000002 002c13aa ole32!CPrivDragDrop::PrivDragDrop+0x172 [com\ole32\com\rot\getif.cxx @ 739] 
53 0087cadc 765f4f3d 74b20d60 0087ccf8 0000000c RPCRT4!Invoke+0x34
54 0087cf14 76337952 22fc0fe0 11c51fd0 1c1d8e78 RPCRT4!NdrStubCall2+0x5ad
55 0087cf5c 763377bb 22fc0fe0 1c1d8e78 11c51fd0 combase!CStdStubBuffer_Invoke+0x92 [onecore\com\combase\ndr\ndrole\stub.cxx @ 1531] 
56 (Inline) -------- -------- -------- -------- combase!InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_ee1df801181086a03fa4f8f75bd5617f>::operator()+0x44 [onecore\com\combase\dcomrem\channelb.cxx @ 1385] 
57 0087cfb0 76337333 22fc0fe0 1c1d8e78 11c51fd0 combase!ObjectMethodExceptionHandlingAction<<lambda_ee1df801181086a03fa4f8f75bd5617f> >+0x9b [onecore\com\combase\dcomrem\excepn.hxx @ 87] 
58 (Inline) -------- -------- -------- -------- combase!InvokeStubWithExceptionPolicyAndTracing+0xe5 [onecore\com\combase\dcomrem\channelb.cxx @ 1383] 
59 0087d07c 7636b5e1 11c51fd0 22fc0fe0 0087d3e8 combase!DefaultStubInvoke+0x263 [onecore\com\combase\dcomrem\channelb.cxx @ 1452] 
5a (Inline) -------- -------- -------- -------- combase!SyncStubCall::Invoke+0x7 [onecore\com\combase\dcomrem\channelb.cxx @ 1509] 
5b (Inline) -------- -------- -------- -------- combase!SyncServerCall::StubInvoke+0xa [onecore\com\combase\dcomrem\servercall.hpp @ 825] 
5c (Inline) -------- -------- -------- -------- combase!StubInvoke+0x2b4 [onecore\com\combase\dcomrem\channelb.cxx @ 1734] 
5d 0087d334 763bf291 1c1d8e78 22fc0fe0 11c51fd0 combase!ServerCall::ContextInvoke+0x461 [onecore\com\combase\dcomrem\ctxchnl.cxx @ 1418] 
5e (Inline) -------- -------- -------- -------- combase!CServerChannel::ContextInvoke+0x72 [onecore\com\combase\dcomrem\ctxchnl.cxx @ 1327] 
5f (Inline) -------- -------- -------- -------- combase!DefaultInvokeInApartment+0xa7 [onecore\com\combase\dcomrem\callctrl.cxx @ 3352] 
60 0087d370 7636c3e7 1c1d8e78 00000001 00000000 combase!ReentrantSTAInvokeInApartment+0x1e1 [onecore\com\combase\dcomrem\reentrantsta.cpp @ 112] 
61 0087d3f4 7636d9f2 22fc0fe0 0c29ba18 163f30b8 combase!AppInvoke+0x7f7 [onecore\com\combase\dcomrem\channelb.cxx @ 1182] 
62 0087d604 7638675a 0087d61f 00000400 00000000 combase!ComInvokeWithLockAndIPID+0x762 [onecore\com\combase\dcomrem\channelb.cxx @ 2290] 
63 (Inline) -------- -------- -------- -------- combase!ComInvoke+0x1c9 [onecore\com\combase\dcomrem\channelb.cxx @ 1803] 
64 (Inline) -------- -------- -------- -------- combase!ThreadDispatch+0x259 [onecore\com\combase\dcomrem\chancont.cxx @ 416] 
65 0087d698 76e3438b 00521568 00000400 0000babe combase!ThreadWndProc+0x3da [onecore\com\combase\dcomrem\chancont.cxx @ 744] 
66 0087d6c4 76e14f8c 76386380 00521568 00000400 USER32!_InternalCallWinProc+0x2b
67 0087d7a8 76e140de 76386380 00000000 00000400 USER32!UserCallWinProcCheckWow+0x3ac
68 0087d81c 76e13ec0 00000400 0087d848 65df3d7c USER32!DispatchMessageWorker+0x20e
69 0087d828 65df3d7c 0087d8ac 0087f59c 00000000 USER32!DispatchMessageW+0x10
6a 0087d848 65e458f1 00000000 65c50000 00000000 wmp+0x1a3d7c
6b 0087f5a0 65e461ac 65c50000 65e7c170 00000000 wmp+0x1f58f1
6c 0087f5bc 00ac24e9 00ac0000 074035be 00000001 wmp!Ordinal3000+0x6c
6d 0087f7f4 74d66359 0068a000 74d66340 0087f860 wmplayer!_PlayerEntry+0x52f
6e 0087f804 771c7b74 0068a000 e01a5779 00000000 KERNEL32!BaseThreadInitThunk+0x19
6f 0087f860 771c7b44 ffffffff 771e8ef4 00000000 ntdll!__RtlUserThreadStart+0x2f
70 0087f870 00000000 00ac1fb0 0068a000 00000000 ntdll!_RtlUserThreadStart+0x1b

As we can see out of bounds access occurred while trying to read a DWORD value from the unallocated/GUARD_PAGE page. Further analysis revealed that while parsing the keys atom structure located in the PoC file at offset : 0x3ED, the method mfmp4srcsnk!CQTMetadataKeysAtom::ParseAtom will stop parsing further keys items if one of them has corrupted size.

We can observe it in the pseudocode below:

Line 1  CVPtrList *__stdcall CQTMetadataKeysAtom::ParseAtom(struct_this_3 *this)
Line 2  {
Line 3    
Line 4    
Line 5          _keys_size = (unsigned int *)_byteswap_ulong(*keys_size);// amount of keys ... here : 0x6
Line 6          keys_size = _keys_size;
Line 7          if ( _keys_size )
Line 8          {
Line 9            while ( 1 )
Line 10           {
Line 11             v32.dword4 = 0;
Line 12             *(_DWORD *)v32.gap0 &= 0xFFFFFFF8;
Line 13             v34 = 0;
Line 14             v33 = 0;
Line 15             v32.dword8 = 0;
Line 16             if ( remainSize < 8 )
Line 17               break;
Line 18             remainKeysAtomSize = remainSize - 8;
Line 19             keyIndex = index + 1;
Line 20             key_object = index + 1;
Line 21             _key_definition_size = _byteswap_ulong(*key_definition_size);
Line 22             _namespace = key_definition_size[1];
Line 23             key_definition_size += 2;
Line 24             __namespace = _byteswap_ulong(_namespace);
Line 25             v27 = remainKeysAtomSize;
Line 26             if ( _key_definition_size > 8 )
Line 27             {
Line 28               if ( remainKeysAtomSize < _key_definition_size - 8 )
Line 29               {
Line 30                 goto @end;
Line 31               }
Line 32               _objCMFBaseString = CMFBaseStringT<unsigned short>( &objCMFBaseString,
Line 33                                                  (LPCSTR)key_definition_size,// key_name
Line 34                                                  _key_definition_size - 8);// key_len
Line 35               CMFBaseStringT<unsigned short>::operator=(&v32, (const unsigned __int16 *)v1, _objCMFBaseString);
Line 36               if ( v24 )
Line 37                 CMFBaseStringT<unsigned short>::_FreeBuffer(&objCMFBaseString);
Line 38               key_definition_size = (unsigned int *)((char *)key_definition_size + _key_definition_size - 8);
Line 39               v27 -= _key_definition_size - 8;
Line 40             }
Line 41             MFDynamicArray<CQTMetadataKeysAtom::KeyMapValue>::AppendItem( &this->dynamicArray,(struct CQTMetadataKeysAtom::KeyMapValue *)&key_object);
Line 42             if ( v34 )
Line 43               CMFBaseStringT<unsigned short>::_FreeBuffer(&v32);
Line 44             index = keyIndex;
Line 45             LOBYTE(_keys_size) = (_BYTE)keys_size;
Line 46             if ( keyIndex >= (unsigned int)keys_size )
Line 47               goto @end;
Line 48             remainSize = v27;
Line 49           }                                     // WHILE
Line 50
Line 51         }
Line 52       }
Line 53
Line 54 @end:
Line 55
Line 56   return v1;
Line 57 }

We can see that in line 28, if the key definition size is bigger that entire remain size of keys atom, the function ends its execution. That situation takes place when a key definition from the offset 0x502 is parsed. Its size is set to 00 30 E8 A9[DWORD] which is much bigger than the defined keys atom size of 0x138. As a consequence at line 41 only 5 of the 6 declared keys definitions are added to the CQTMetadataKeysAtom::KeyMapValue container .

In a further phase of the MP4 file metadata parsing, the ilst atom is parsed. That atom should contain 6 definitions of data related with corresponding keys from keys atom. An out-of-bounds read vulnerability occurs because there is no check in CQTMetadataKeysAtom::GetKeyForIndex that verifies whether the amount of keys definition read from keys atom is the same as an available keys data in ilst atom.

Line 1  int __thiscall CQTMetadataKeysAtom::GetKeyForIndex(struct_container *container, int index, PDWORD element, int a4)
Line 2  {
Line 3    int v4; // edi
Line 4    struct_container *v5; // ebx
Line 5    CQTMetadataKeysAtom ptrCQTMetadataKeysAtom; // edx
Line 6    CVPtrList *v7; // ecx
Line 7    struct CallStackContext *v8; // eax
Line 8    struct CallStackContext *v9; // eax
Line 9    int v10; // ecx
Line 10   int v11; // ecx
Line 11   char v13; // [esp+Fh] [ebp-1h]
Line 12
Line 13   v4 = 0;
Line 14   v5 = container;
Line 15   if ( index && container->size >= (unsigned int)(index - 1) )
Line 16   {
Line 17     ptrCQTMetadataKeysAtom = container->ptrCQTMetadataKeysAtom;
Line 18     *element = ptrCQTMetadataKeysAtom[index]->strValue.strLen
Line 19     CMFBaseStringT<unsigned short>::operator=((struct_this_2 *)a4, 0, &ptrCQTMetadataKeysAtom[index]->strValue);

In the method CQTMetadataKeysAtom::GetKeyForIndex an out-of-bounds read occurs at line 18 and line 19 when trying to read the key element with index 6.

We can check the boundaries of the ptrCQTMetadataKeysAtom container:

eax=04d1f5e0 ebx=04d71ee0 ecx=04d71ee0 edx=03418fe8 esi=000000a8 edi=00000000
eip=79373a12 esp=04d1f5a0 ebp=04d1f5b0 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
mfmp4srcsnk!CQTMetadataKeysAtom::GetKeyForIndex+0x25:
9373a12 8b4c32e8        mov     ecx,dword ptr [edx+esi-18h] ds:002b:03419078=893500e8
0:005> !heap -p -a 0x03418fe8
    address 03418fe8 found in
    _HEAP @ 3410000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        03418fd0 0015 0000  [00]   03418fe8    0008c - (busy)
        77233484 ntdll!RtlpCallInterceptRoutine+0x00000026
        771f0a8a ntdll!RtlpAllocateHeapInternal+0x00055c8a
        7719adee ntdll!RtlAllocateHeap+0x0000003e
        759a7610 msvcrt!malloc+0x00000090
        759a768b msvcrt!realloc+0x0000001b
        79376f93 mfmp4srcsnk!MFDynamicArray<CQTMetadataKeysAtom::KeyMapValue>::Reserve+0x0000001d
        79372a92 mfmp4srcsnk!MFDynamicArray<CQTMetadataKeysAtom::KeyMapValue>::AppendItem+0x0000001e
        7937420c mfmp4srcsnk!CQTMetadataKeysAtom::ParseAtom+0x0000027c
        792c4a8b mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000011b
        792cd5ca mfmp4srcsnk!CMP4MetadataAtom::CreateChildAtom+0x000000ba
        792c43cb mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x000000bb
        792c42a8 mfmp4srcsnk!CQTAtom::ScanChildren+0x000000c8
        792c53ad mfmp4srcsnk!CQTAtom::ParseAtom+0x000000fd
        792e48a1 mfmp4srcsnk!CMP4MetadataAtom::ParseAtom+0x00000041
        792c4a8b mfmp4srcsnk!CQTAtom::CreateTypedAtom+0x0000011b
        792c693e mfmp4srcsnk!CQTMovie::CreateChildAtom+0x0000034e
        792c4559 mfmp4srcsnk!CQTAtom::ScanChildrenInBuffer+0x00000249
        792c42a8 mfmp4srcsnk!CQTAtom::ScanChildren+0x000000c8
        792b5d78 mfmp4srcsnk!CQTMovie::CreateQTMovie+0x00000098
        792b4124 mfmp4srcsnk!CQTMovie::CreateMovieFromBuffer+0x000001c6
        792b39a6 mfmp4srcsnk!MFCreateQTMovie+0x00000030
        792b2ff3 mfmp4srcsnk!CMPEG4MediaSourcePlugin::FinishParsingHeader+0x000000d2
        792b45d7 mfmp4srcsnk!CMPEG4MediaSourcePlugin::BeginParsingHeader+0x00000335
        792b5255 mfmp4srcsnk!CMPEG4MediaSourcePlugin::ParseHeaderInternal+0x00000232
        792b4a72 mfmp4srcsnk!CMPEG4MediaSourcePlugin::ParseHeader+0x00000332
        792afaf0 mfmp4srcsnk!CMFByteStreamMediaSource::OnByteStreamReadHeader+0x00000184
        792af966 mfmp4srcsnk!CMFByteStreamMediaSource::OnByteStreamReadHeaderAsyncCallback::Invoke+0x00000016
        6811417e RTWorkQ!CSerialWorkQueue::QueueItem::ExecuteWorkItem+0x0000009e
        681186ef RTWorkQ!ThreadPoolWorkCallback+0x000001ff
        771b7dd4 ntdll!TppWorkpExecuteCallback+0x00000144
        771b6adc ntdll!TppWorkerThread+0x0000072c
        74d66359 KERNEL32!BaseThreadInitThunk+0x00000019

0:005> ?03418fe8 + 0x8C
Evaluate expression: 54628468 = 03419074

So the boundary ends at address 0x03419074 and we can see at line 18 that we read a DWORD value from address 0x03419078 (which is 4 bytes further). The content of the corresponding memory looks as follows:

Last elements in a container : 28 bytes size
00000000`03419058  00000005 6D647461 00000000 00000000  ....atdm........
00000000`03419068  00000022 00000023 02E44A88 

space allocated by a different object
00000000`03419074  00000000 
00000000`03419078  893500E8 420024E4 04D2BB44 04D71F50  ..5..$.BD...P...
00000000`03419088  00000001 05020018 792773CC 03419090  .........s'y..A.

The pointer obtained for the string at line 19 is passed to the string assignment operator:

0:005> p
eax=0341907c ebx=04d71ee0 ecx=04d1f5ec edx=03418fe8 esi=000000a8 edi=00000000
eip=79373a21 esp=04d1f59c ebp=04d1f5b0 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
mfmp4srcsnk!CQTMetadataKeysAtom::GetKeyForIndex+0x34:
79373a21 e84c35f6ff      call    mfmp4srcsnk!CMFBaseStringT<unsigned short>::operator= (792d6f72)
0:005> dd esp L1
04d1f59c  0341907c

Based on the values related to that string object (data ptr and size) a memcpy operation is performed. If attackera are able to massage the heap properly and sets values controlled by them, this may lead to an informaiton disclosure or potential heap corruption.

Below is an example where we set String->data ptr and String->size based on values controlled by us:

0:005> p
eax=033cbe5c ebx=033cbd48 ecx=04cef5ec edx=033cbdc8 esi=04cef5ec edi=00000000
eip=65b46f8b esp=04cef590 ebp=04cef594 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
mfmp4srcsnk!CMFBaseStringT<unsigned short>::operator=+0x19:
65b46f8b ff7008          push    dword ptr [eax+8]    ds:002b:033cbe64=04db1f78
0:005> ed 033cbe64 0x31337
0:005> p
eax=033cbe5c ebx=033cbd48 ecx=04cef5ec edx=033cbdc8 esi=04cef5ec edi=00000000
eip=65b46f8e esp=04cef58c ebp=04cef594 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
mfmp4srcsnk!CMFBaseStringT<unsigned short>::operator=+0x1c:
65b46f8e ff7010          push    dword ptr [eax+10h]  ds:002b:033cbe6c=05020018
0:005> ed 033cbe6c 0x41414141
0:005> g
(951c.11a54): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=414767af ebx=00031337 ecx=0001899b edx=00000002 esi=41414141 edi=02d0a5e8
eip=759e91ea esp=04cef54c ebp=04cef554 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
msvcrt!memcpy+0x5a:
759e91ea f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

Timeline

2020-02-11 - Vendor Disclosure

2020-03-20 - Vendor Patched and assigned CVE
2020-04-14 - Public Release

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.