CVE-2015-3667
There is a remote code execution vulnerability in Apple Quicktime. An attacker who can control the data inside an stbl atom in a .mov file can cause an undersized allocation which can lead to an out-of-bounds read. An attacker can use this to create a use-after-free scenario that could lead to remote code execution.
Apple Quicktime 7.7.5 - Windows 7 32-bit Vulnerable
Apple Quicktime 7.7.6 - Windows 7 32-bit Vulnerable
https://www.apple.com/quicktime/
The function QuickTimeMPEG4!0x147f0 is responsible for processing the data in an hdlr atom. A 16-byte memory region is allocated near the beginning of the function.
28 object_ref = AllocWrap(16, &v13); // returns allocation of size 16
If the hdlr subtype field in an mdia atom is set to ‘vide’, this reference is passed to a set of two functions. The first function swaps out the reference in object_ref for a bigger object, one of size 0xb0 bytes and the second function operates on this new object.
42 Determine_4CC(v5, &The_4CC_from_obj, 0, 0);
43 switch ( The_4CC_from_obj )
44 {
45 case 'odsm':
46 case 'sdsm':
47 sub_6A8A9FB0(v4, &v20, &v22, &v16, &v21);
48 v16 |= 1u;
49 v20 = -1;
50 sub_6A8A9F90(v4, -1, v22, v16, v21);
51 break;
52 case 'hint':
53 sub_6A8A9E90(v4, 0);
54 break;
55 case 'vide':
56 sub_6A8A9F10(v5, 1, object_ref); <- Back-to-back function calls
57 if ( (unsigned __int8)sub_6A894F10() ) <----Back-to-back function calls
58 {
59 v6 = sub_6A8AA190(v4, 'visu', 'cldi', 8, &v23, 0);
At some point up the call stack for the first of these two functions, the reference in question is passed to the function QuickTime!0x73e0f0. However, when the stbl atom is missing from the file (or the 4CC is corrupted) the object at eax does not get populated. When this happens, the check at line 15 will pass and an error code (0xfffff809) will be passed back down the call stack.
7 v3 = *(_DWORD *)(a1 + 66);
(...)
12 else if ( v3 )
13 {
14 v5 = *(_DWORD *)v3;
15 if ( a2 < 1 || a2 > *(_DWORD *)(v5 + 76) ) <---object+0x4c
16 {
17 result = 0xFFFFF809;
18 }
19 else
20 {
21 *(_DWORD *)ptr_to_args = *(_DWORD *)(**(_DWORD **)(v5 + 168) + 4 * a2);
22 result = 0;
23 }
24 }
This series of calls would normally lead to the replacement of the object reference lie in the function QuickTime!0x748a40. However, because the error code returned down the stack isn’t zero, the branch below is taken and the code path skipped.
9 LOWORD(result) = sub_67183760(*(_DWORD *)(a1 + 4), a2, &a1);
10 if ( (_WORD)result ) <----------- result not zero
11 {
12 result = (signed __int16)result;
13 }
14 else
15 {
16 v4 = sub_6717C2C0(a1, 0);
17 v5 = ptr_to_tiny;
18 v6 = v4;
19 v7 = sub_6717C2B0(ptr_to_tiny, v4);
20 if ( !v7 )
21 to_memcpy(*(_DWORD *)a1, *(_DWORD *)v5, v6);
22 result = v7;
23 }
24 return result;
Eventually, the calls return and the function at line 57 of QuickTimeMPEG4!0x147f0 is called.
56 sub_6A8A9F10(v5, 1, object_ref); <- Back-to-back function calls
57 if ( (unsigned __int8)sub_6A894F10() ) <-Back-to-back function calls
Code execution makes its way up to the function QuickTime!0x21ab00.
11 v3 = *(_DWORD *)small_object;
12 result = 86;
13 if ( !*(_WORD *)(*(_DWORD *)small_object + 84) )
14 result = 8 * *(_WORD *)(v3 + 92) + 102;
A read of 2 bytes is attempted at an offset of 84 bytes into the 16-byte object, resulting in an out-of-bounds read.
Crash Information
eax=03454fa8 ebx=1bceadbc ecx=1bceadbc edx=0000000c esi=1898ffe8 edi=002bc370
eip=6a35a778 esp=002bc358 ebp=002bc3b0 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210206
QuickTime!LIST_ComponentDispatch+0x160318:
6a35a778 66837e5400 cmp word ptr [esi+54h],0 ds:0023:1899003c=????
STACK_TEXT:
002bc3b0 6a35a9ea 1bceadbc 70617370 00000001 QuickTime!LIST_ComponentDispatch+0x160318
002bc440 68b84f2e 1bceac9e 1bceadbc 00005d98 QuickTime!LIST_ComponentDispatch+0x16058a
00000000 00000000 00000000 00000000 00000000 QuickTimeMPEG4!EatMPEG4ComponentDispatch+0x6e
Ryan Pentney and Richard Johnson of Cisco Talos