Recently I’ve been receiving phishing-spam in the form of official-looking Amazon.com invoices. Curiosity got the better of me and I clicked on the phishing link. The page that came up was blank. A quick source view revealed a bunch of obfuscated javascript.
I wanted to see how it worked.
Here is a sample line of the code:
mGdujq[‘euvLaulm'[VvIf](/[muzLc]/g, EWgUi)] \
(ltY(mGdujq[[‘uhnKehsKcKaKpleo'[VvIf](/[oKhlE]/g, EWgUi)]](IuO)));
Now what’s going on here?
Well, plain as day in the source I see a couple very important lines that will help decode this. The lines are:
var EWgUi = ”;
var mGdujq = this;
var VvIf = ” + ‘replace’;
Armed with this information the line decodes easily before our eyes to
this[‘euvLaulm'[replace](/[muzLc]/g,”) \
(ltY(this[[‘uhnKehsKcKaKpleo'[replace](/[oKhlE]/g,”)]](IuO)));
What’s left to decode is the use of shorthand regular expressions. For example let’s look at this piece of code
‘euvLaulm'[replace](/[muzLc]/g,”)
‘euvLaulm’ is just a regular old string. You can call the string’s replace function in many different ways such as:
var str = ‘euvLaulm’; str.replace();
‘euvLaulm’.replace();
‘euvLaulm'[replace]();
The regex /[muzLc]/g simply matches any character within the square brackets. The full line of code calls for every match to be replaced with ” (an empty string) or in other words, to delete those characters from the string.
euvLaulm
The result is the string ‘eval’.
So the fully interpreted line of javascript reads as follows:
this[eval](ltY(this[[unescape]](IuO)));
Or in code more readable to my own eyes:
this.eval( ltY( this.unnescape( IuO )));
Strewn throughout the javascript are lots of variable declarations that create strings of seemingly random letters and numbers. Upon close inspection you might notice that there’s a pattern to the strings; they consist of alternating hex and non-hex characters. (A hex character or value is 0-9 and a-f).
Near the end of the code all these strings are concatenated and a series of replace operations are performed to replace all the non-hex characters with ‘%<hex character>’. The result is a string of URL escape sequences (a percent symbol followed by 2 hex characters). This string is stored in the variable IuO.
The URL escaped data is then unescaped to create an array of bytes (aka, a string, except the bytes aren’t all printable characters, so I can’t call it a string). This data is passed to the ltY function which performs a ( <byte> XOR 13 ) operation on each byte of data. The result is a string of HTML that creates a hidden iframe to some porn referral page and a META refresh that redirects the user to a male supplements web site after 4 seconds.
That was fun. A little sleuthing and puzzle solving. But what is there to take away from all this?
First was myself learning new ways to use and abuse javascript syntax such as ‘string'[function].
Also curious was the large amount of superfluous statements in the code. Variables would be created without initialization. They they’d be initialized to an empty string. Then they’d be set to their real value. Three statements to perform an operation that could be done in one. I imagine this, along with the use of random upper and lowercase letters used as variables AND data make the code more difficult to parse by hand (or by eye). But a few minutes and a bit of perseverance will overcome that. However that shows these types of scams are designed with the user who tries to perform a cursory inspection of the underlying code in mind.
The multiple decoding steps to arrive at the final “attack” HTML indicates to me the code is designed to circumvent string-comparison spam filters. That there was more than one decoding step and that there’s a bunch of extra, useless javascript (if/else blocks with one assignment to an unused variable) makes me wonder if this code was also created to circumvent spam filters that are javascript-aware. It’s working so far. My institution’s normally solid spam filtering software has let this one slip by twice in the last week.
And it’s nice to see what kinds of tricks spammers have up their sleeves.