这个混淆的JavaScript是如何工作的?

下面的JavaScript如何工作?

我知道这是缩小的代码,但是我已经尝试了对它进行一些混淆处理,但我无法弄清楚它是如何实现这种效果的。 我可以看到,它使用string迭代某种types,使用Date对象,奇怪的string操作,math函数,然后代码打印自己。

一个最小的例子怎么能改写同样的效果呢?

eval(z='p="<"+"pre>"/* ,.oq#+ ,._, */;for(y in n="zw24l6k\ 4e3t4jnt4qj24xh2 x/* =<,m#F^ AW###q. */42kty24wrt413n243n\ 9h243pdxt41csb yz/* #K q##H######Am */43iyb6k43pk7243nm\ r24".split(4)){/* dP cpq#q##########b, */for(a in t=pars\ eInt(n[y],36)+/* p##@###YG=[#######y */(e=x=r=[]))for\ (r=!r,i=0;t[a/* d#qg `*PWo##q#######D */]>i;i+=.05)wi\ th(Math)x-= /* aem1k.com Q###KWR#### W[ */.05,0>cos(o=\ new Date/1e3/* .Q#########Md#.###OP A@ , */+x/PI)&&(e[~\ ~(32*sin(o)*/* , (W#####Xx######.P^ T % */sin(.5+y/7))\ +60] =-~ r);/* #y `^TqW####P###BP */for(x=0;122>\ x;)p+=" *#"/* b. OQ####x#K */[e[x++]+e[x++\ ]]||(S=("eval"/* l `X#####D , */+"(z=\'"+z.spl\ it(B = "\\\\")./* G####B" # */join(B+B).split\ (Q="\'").join(B+Q/* VQBP` */)+Q+")//m1k")[x/2\ +61*y-1]).fontcolor/* TP */(/\\w/.test(S)&&"#\ 03B");document.body.innerHTML=p+=B+"\\n"}setTimeout(z)')// 

的jsfiddle

前言 :我在http://jsfiddle.net/WZXYr/2/上大量美化和注释了代码;

考虑最外层:

 eval(z = '...'); 

代码string存储在variablesz 。 赋值运算符返回分配的值,所以代码string也作为parameter passing给eval

代码stringzeval内部运行。 代码是非常钝的,即使清理,但似乎:

  1. parsing一个由36个数字组成的string,由字符4
  2. 填充值的映射,使用全局variablesexy来保存映射状态。 地图状态部分地是挂钟上当前秒的function( new Date / 1e3 )。
  3. 使用映射值,代码将生成一个输出stringp
    • 代码使用p += " *#"[index]来决定是否使用空格,星号或散列标记,其中index实际上是e[x++] + e[x++] (如上所述, ex负责为地图状态)
    • 如果索引大于" *#"的长度,则存在回退代码,用来自z字符填充输出p 。 内部字符用animation字符填充,外部字符从z拉出。

在代码的结尾,有一个setTimeout(z)的调用,它asynchronous评估代码stringzz重复调用允许代码循环。

简单的例子:

这是一个超级简单的版本( http://jsfiddle.net/5QXn8/ ):

 eval(z='p="<"+"pre>";for(i=0;i<172;++i)if(i > 62 && i < 67)p+="!---"[~~(new Date/1e2 + i)%4];else p += ("eval(z=\'" + z + "\')")[i];document.body.innerHTML = p;setTimeout(z)') 
  1. for循环将每个字符添加到输出stringp (string长度为172个字符):

     for(i=0;i<172;++i) 
  2. 内部条件决定我们是否位于62到67位之间的字符,这些字符是animation字符:

     if(i > 62 && i < 67) 
  3. 如果是,则打印出来!--- ,根据第二个挂钟值的十分之一进行转换。 这提供了animation效果。

     p+="!---"[~~(new Date/1e2 + i)%4] 

    (所有在new Date周围的不安实际上只是在那里将date值转换为0和3之间的数字。)

  4. 否则,如果我们不是animationangular色,则从由其定义的string中打印index- i字符

     "eval(z='" + z + "')" 

    也就是说,由eval('')包围的代码stringz

  5. 最后,输出string并使用setTimeout排队另一个z

     document.body.innerHTML = p;setTimeout(z) 

请注意,我的最终结果并不完全正确 – 我还没有把反斜杠算到最后 – 但是它应该仍然给你一个这个技术如何工作的很好的概念。

这是注释的来源。 Ps:我是作者;)

 function z(){ // will be replaced with eval p = "<" + "pre>"; // use <pre> tag for formatted output for ( // loop though lines y in n = ( // y - the line number "zw24" + // n - the encoded data "l6k4" + // every line holds encoded data "e3t4" + "jnt4" + // string will be concated in build process "qj24" + "xh2 4" + // data after spaces will be ignored but "2kty24" + // … is used to not break block comments "wrt4" + // … which will save some chars "13n24" + "3n9h24" + "3pdxt4" + "1csb 4" + "3iyb6k4" + "3pk724" + "3nmr24" ).split(4) // data will be split by (unused) 4 ){ for ( // loop throug every char in line a in t = parseInt( // numbers are encoded as string n[y], // … with a base of 36 36 ) + ( // large number will be converted to string e = // e - holds the rendered globe x = // x - horizonal position r = [] // r - bitmap flag if pixel is set ) ){ r = !r; // toggle binary flag for ( // look though bitmap states i = 0; t[a] > i; // draw pixel t[a]-times i += .05 ) with (Math) // refer to Math later x -= .05, 0 > cos( // prevent backface visibility o = new Date / 1e3 + // get rotation based on current time x / PI ) && ( e[ // access matrix ~~( // convert float to integer sin(o) * // rotate around y axis sin(.5 + y/7) * 32 // scale up the globe ) + 60 // move to center ] = -~r // store bitmap state in render matrix ) } for ( // loop through columns x = 0; 122 > x; // break after char 122 ) p += " *#"[ // add space, asterisk or hash e[x++] + // … based pixel opacity e[x++] ] || (S = ( // otherwise use the original code "eval(z='" + // inception of missing "eval" statement z .split(B = "\\") // escape \ with \\ .join(B + B) .split(Q = "'") // escape ' with \' .join(B + Q) + Q + // add missing ') ")////////" // add extra chars to fill mapping )[ x / 2 + // get character at current position 61 * y-1 ] ).fontcolor( // colorize outpu /\w/.test(S) && // test for [0-9A-Z] "#03B" // render blue // otherwise pink (default) ); document.body.innerHTML = // render output p += // append new line B + // add backspace "\n"; // add new line } setTimeout(z) // render animation on next frame } z() 

这里是另一个手动去混淆的版本,将所有初始化从expression式转移到自己的语句中:

 z='p="<"+"pre>"/* ,.oq#+ ,._, */;for(y in n="zw24l6k\ 4e3t4jnt4qj24xh2 x/* =<,m#F^ AW###q. */42kty24wrt413n243n\ 9h243pdxt41csb yz/* #K q##H######Am */43iyb6k43pk7243nm\ r24".split(4)){/* dP cpq#q##########b, */for(a in t=pars\ eInt(n[y],36)+/* p##@###YG=[#######y */(e=x=r=[]))for\ (r=!r,i=0;t[a/* d#qg `*PWo##q#######D */]>i;i+=.05)wi\ th(Math)x-= /* aem1k.com Q###KWR#### W[ */.05,0>cos(o=\ new Date/1e3/* .Q#########Md#.###OP A@ , */+x/PI)&&(e[~\ ~(32*sin(o)*/* , (W#####Xx######.P^ T % */sin(.5+y/7))\ +60] =-~ r);/* #y `^TqW####P###BP */for(x=0;122>\ x;)p+=" *#"/* b. OQ####x#K */[e[x++]+e[x++\ ]]||(S=("eval"/* l `X#####D , */+"(z=\'"+z.spl\ it(B = "\\\\")./* G####B" # */join(B+B).split\ (Q="\'").join(B+Q/* VQBP` */)+Q+")//m1k")[x/2\ +61*y-1]).fontcolor/* TP */(/\\w/.test(S)&&"#\ 03B");document.body.innerHTML=p+=B+"\\n"}setTimeout(z)'; p = "<" + "pre>"; n = ["zw2", "l6k", "e3t", "jnt", "qj2", "xh2 x/* =<,m#F^ AW###q. */", "2kty2", "wrt", "13n2", "3n9h2", "3pdxt", "1csb yz/* #K q##H######Am */", "3iyb6k", "3pk72", "3nmr2", ""] for (y in n) { e = []; x = 0; r = true; t = parseInt(n[y], 36) + ""; for (a in t) { r = !r for (i = 0; i < t[a]; i += 0.05) { x -= 0.05; o = new Date / 1e3 + x / Math.PI if (Math.cos(o) < 0) e[~~(32 * Math.sin(o) * Math.sin(0.5 + y / 7)) + 60] = -~r; } for (x = 0; x < 122;) { S = "eval" + "(z='" + z.split(B = "\\").join(B + B).split(Q = "'").join(B + Q) + Q + ")//m1k" p += " *#"[e[x++] + e[x++]] || S[x/2+61*y-1]).fontcolor(/\w/.test(S[x/2+61*y-1]) && "#03B"); } p += B + "\n"; document.body.innerHTML = p; } setTimeout(z) 

这是发生了什么事情:

  • z是包含所有代码的多行string。 这是eval
  • 在代码的最后, z被传递给setTimeout 。 它像requestAnimationFrameeval一起工作,以最高的速度在一个区间内进行评估。
  • 代码本身初始化p ,HTML将被附加到的string缓冲区,以及n ,一个由base-36编码的数字组成的数组(由"4"连接成一个string,注释是parseInt不考虑的无关垃圾)。
  • n中的每个数字都编码一行( n.length == 16 )。 现在列举 。
  • 一堆variables被初始化,一些伪装成e数组,然后在使用时被转换为数字( x )或布尔值( r )或string( t )。
  • 数字t中的每个数字都是枚举的,每转都反转布尔值。 对于不同的angular度x ,取决于当前时间 new Date / 1000 (这样就给出了一个animation),数组e用一些按位运算符填充 – 当r是假时为1 ,当r为真时为2 s 。
  • 然后,一个循环遍历图像的61列,从x=0到122以两步进行迭代,将单个字符附加到p
  • B是反斜杠,stringS是通过转义反斜杠和撇号从代码stringz构build的,以获得它在源代码中查找内容的准确表示。
  • 来自e每两个连续的数字被添加并用于从" *#"访问字符,以build立animation图像。 如果没有定义其中的一个索引,则NaN索引parsing为一个未定义的字符,而是从Sstring中取出相应的字符(检查公式x/2+61*y-1 )。 如果该字符应该是单词字符 ,则使用fontcolorstring方法对其进行着色。
  • 在每一行之后,尾部的退格和换行符被添加到p ,并且HTMLstring被分配给文档主体。

同样的效果怎么可以重写一个最小的例子?

这是另一个例子:

 setInterval(z='s=("setInterval(z=\'"+\ z.replace(/[\\\\\']/g,"\\\\$&")+"\')"\ ).match(/.{1,37}/g).join("\\\\\\n");d\ ocument.body.innerHTML=\"<\\pre>"+ss\ lice(0, 175)+String( + new Date()).fo\ ntcolor("red")+s.slice(188)') 

( 演示在jsfiddle.net )

它有这种animation需要的所有相关的东西:

  • setIntervalDate为animation
  • 自己的代码重构( quine- like),在这里:

     s = ( "setInterval(z='" // the outer invokation + z.replace(/[\\\']/g,"\\$&") // the escaped version + "\')" ) // the end of the assignment .match(/.{1,37}/g).join("\\\n"); // chunked into lines 
  • 通过document.body.innerHTML和一个<pre>元素输出

  • 用animationstringreplace部分代码

一个包含所有代码的string被计算出来,并且超时会产生循环; string存储在名为z的variables中,在代码中间,注释/**/有一个“地球ASCII艺术”。 该代码parsing评论和更改文档内容,保持js和更新艺术。 贝娄只是代码片:

  p="<pre>"; for(y in n="zw24l6k4e3t4jnt4qj24xh2 x42kty24wrt413n243n9h243pdxt41csb yz43iyb6k43pk7243nmr24".split(4)){ for(a in t = parseInt(n[y],36)+(e=x=r=[])) for(r=!r,i=0;t[a]>i;i+=.05) with(Math) x-= .05,0>cos(o=new Date/1e3+x/PI)&&(e[~~(32*sin(o)*sin(.5+y/7))+60] =-~ r); for(x=0;122>x;) p += " *#"[e[x++]+e[x++\]] || (S=("eval"+"(z=\'"+z.split(B = "\\\\").join(B+B).split(Q="\'").join(B+Q)+Q+")//m1k")[x/2+61*y-1]).fontcolor(/\\w/.test(S)&&"#\03B"); p += B+"\\n" document.body.innerHTML= p }