这个混淆的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
。
代码stringz
在eval
内部运行。 代码是非常钝的,即使清理,但似乎:
- parsing一个由36个数字组成的string,由字符
4
。 - 填充值的映射,使用全局variables
e
,x
和y
来保存映射状态。 地图状态部分地是挂钟上当前秒的function(new Date / 1e3
)。 - 使用映射值,代码将生成一个输出string
p
- 代码使用
p += " *#"[index]
来决定是否使用空格,星号或散列标记,其中index
实际上是e[x++] + e[x++]
(如上所述,e
和x
负责为地图状态) - 如果索引大于
" *#"
的长度,则存在回退代码,用来自z
字符填充输出p
。 内部字符用animation字符填充,外部字符从z
拉出。
- 代码使用
在代码的结尾,有一个setTimeout(z)
的调用,它asynchronous评估代码stringz
。 z
重复调用允许代码循环。
简单的例子:
这是一个超级简单的版本( 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)')
-
for
循环将每个字符添加到输出stringp
(string长度为172个字符):for(i=0;i<172;++i)
-
内部条件决定我们是否位于62到67位之间的字符,这些字符是animation字符:
if(i > 62 && i < 67)
-
如果是,则打印出来
!---
,根据第二个挂钟值的十分之一进行转换。 这提供了animation效果。p+="!---"[~~(new Date/1e2 + i)%4]
(所有在
new Date
周围的不安实际上只是在那里将date值转换为0和3之间的数字。) -
否则,如果我们不是animationangular色,则从由其定义的string中打印index-
i
字符"eval(z='" + z + "')"
也就是说,由
eval('
和')
包围的代码stringz
。 -
最后,输出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
。 它像requestAnimationFrame
和eval
一起工作,以最高的速度在一个区间内进行评估。 - 代码本身初始化
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为一个未定义的字符,而是从S
string中取出相应的字符(检查公式x/2+61*y-1
)。 如果该字符应该是单词字符 ,则使用fontcolor
string方法对其进行着色。 - 在每一行之后,尾部的退格和换行符被添加到
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需要的所有相关的东西:
-
setInterval
和Date
为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 }
- jQuery从无序列表中删除所有列表项
- React – 在挂载的组件上设置setState()
- testingjQueryUI是否已经加载
- 找不到模块'../build/Release/bson'] code:'MODULE_NOT_FOUND'} js-bson:无法加载c ++ bson扩展,使用纯JS版本
- 为什么浏览器在经过validation的XMLHttpRequest之后不重复使用授权标头?
- 知道何时加载图像的Javascriptcallback
- 你什么时候应该使用escape来代替encodeURI / encodeURIComponent?
- 作为一个if语句使用&&短路?
- 如何从jQuery返回的XMLDocument(跨浏览器)获取整个XMLstring?