By Secunia Research
A step-by-step discussion of the latest Flash Player 0-day exploit
As mentioned in our previous blog post and Secunia Advisory SA44119, a new Adobe Flash Player 0-day vulnerability is currently being exploited in the wild through Microsoft Word (*.doc) documents. The vulnerability is currently unpatched, though Adobe has scheduled a fix for Flash Player tomorrow, Friday April 15th and for Adobe Reader/Acrobat on June 14th.
The Word document is named: "Disentangling Industrial Policy and Competition Policy.doc" and embeds a SWF file at offset 0x2E08, the stream having a size of 0x2775 bytes.
00002E00 66 55 66 55 75 27 00 00 46 57 53 0A 75 27 00 00 fUfUu'..FWS.u'..
The embedded SWF loads a secondary SWF file at runtime through a call to flash.display.Loader.loadBytes() from the "t" property. It is this secondary SWF that actually triggers the vulnerability, but it is heavily obfuscated and, therefore, not straight-forward to analyse as it manages to confuse ActionScript disassemblers, some crashing while others stop providing disassembly prematurely.
The first apparently intentional alteration of the file is the incorrect declaration of the size of a group of included constants. Namely, the size value of 0x15 included at offset 0x3D in the SWF does not correspond to the actual size of the constants (0x14), causing some disassemblers to interpret following code from an incorrect offset.
00000030 0E 12 9D 02 00 4C 04 9D 02 00 18 00 88 15 00 09 .....L..........
This can be fixed by adding one character to the last constant.
00000050 00 49 49 00 8E 11 00 64 65 66 61 75 6C 74 00 01 .II....default..
Disassemblers still refuse to present proper disassembly due to the incorrect structure of the included DOACTION tag (DOACTION tags contain ActionScript bytecode in AVM2). The size of the DOACTION tag is declared as 0x05A7 inside the SWF, but the last included tags are incorrectly formed, causing overly large read attempts. This can be fixed by setting all bytes starting at offset 0x5B2 to zero (interpreted as end action tags).
It is now possible to extract the disassembly, but other problems are encountered: Several unnecessary instructions making the code difficult to read are included, but can be eliminated.
An example is the code block:
push 1212792920, -1212792921
This can eliminated completely since label2 is reached in all cases. Many other cases involving unnecessary stack manipulations can also be eliminated in the process.
The SWF is further obfuscated through the use of several jumps back and forth inside the code.
An example of this is:
This can be simplified by moving label7 before label3 and eliminating both "branch" instructions.
After obtaining a better arranged code stream, the next step is to decode two important string constants included in an encoded form. These strings are included as: "VkduhgRemhfw1surwrw|sh" and "Gdwh1surwrw|sh". By studying the disassembly it can be observed that the "VkduhgRemhfw1surwrw|sh" constant is passed in a call to an internally declared "default" function prior to further usage.
constants 'String', 'length', 'charCodeAt', 'fromCharCode', 'charAt', 'case',
The "default" function transforms an input string by subtracting 3 from each of its characters.
push r:3, r:1, 1, r:2, c:2 //String.charCodeAt
After applying the transformation to the encoded constants, the "SharedObject.prototype" and "Date.prototype" strings are obtained. Further simplification of the code is then possible by eliminating the encoding function and various other instructions.
All in all, more than 250 lines of assembly can be eliminated in the process, resulting in the following ActionScript code when decompiled:
Date.prototype.c_fun = SharedObject.prototype.getSize;
Further analysis of the vulnerability caused by this code shows that it's another object type confusion vulnerability occurring in SharedObject.prototype.getSize() when a Date class is extended by adding a custom function obtained via SharedObject.prototype.getSize. The Date object is initialised with the 1.41466385537348e-315 value, which transforms to 0x11111110 when saved in memory. 0x11111110 is an address suitable for heap spraying.
When the custom Date.c_fun() function is called, SharedObject.prototype.getSize() is reached and incorrectly interprets the passed Date object as having a SharedObject type, attempting to use 0x11111110 as a pointer to a virtual function table.
In conclusion, the vulnerability is proved to be obfuscated to a large degree and is also technically interesting in nature. The SWF requires no manipulation of the ActionScript bytecode after compilation from its source.