这个混淆的JavaScript是如何工作的
How does this obfuscated JavaScript work?
以下JavaScript是如何工作的?
我知道它是缩小的代码。我尝试对它进行一些去混淆,但我无法清楚地了解它如何实现这种效果。 我可以看到它正在使用字符串进行某种迭代,使用 Date 对象,奇怪的字符串操作,数学函数,然后代码自行打印。
如何用最小的例子重写相同的效果?
eval(z='p="<"+"pre>"/* ,.oq#+ ,._, */;for(y in n="zw24l6k'
4e3t4jnt4qj24xh2 x/* =<,m#F^ A W###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 = '...');
代码字符串存储在变量 z
中。赋值运算符返回分配的值,因此代码字符串也作为参数传递到 eval
中。
代码字符串z
在 eval
内运行。代码非常迟钝,即使经过清理,但似乎:
- 解析一串以 36 为底的数字,由字符
4
描述。 - 使用全局变量
e
、x
和y
填充值映射来保存映射状态。地图状态部分是挂钟上当前秒的函数(new Date / 1e3
)。 - 使用映射值,代码生成输出字符串,
p
- 代码使用
p += " *#"[index]
来决定是否使用空格、星号或哈希标记,其中index
实际上是e[x++] + e[x++]
(如上所述,e
和x
负责映射状态) - 如果索引大于
" *#"
的长度,则有回退代码用z
中的字符填充输出p
。内部字符填充动画角色,而外部字符从z
中提取。
- 代码使用
在代码的末尾,有一个对setTimeout(z)
的调用,它异步计算代码字符串z
。这种对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
循环将每个字符添加到输出字符串p
(字符串长度为 172 个字符):for(i=0;i<172;++i)
内部条件决定了我们是否位于位置 62 到 67 之间的角色上,这些角色是动画角色:
if(i > 62 && i < 67)
如果是,则打印出
!---
,根据第二个挂钟值的十分之一进行移动。这将提供动画效果。p+="!---"[~~(new Date/1e2 + i)%4]
(围绕
new Date
的所有肮脏实际上只是为了将日期值转换为 0 到 3 之间的数字。否则,如果我们不在动画字符上,则从定义的字符串中打印索引
i
字符"eval(z='" + z + "')"
也就是说,代码字符串
z
被eval('
和')
包围。最后,输出字符串并使用
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()
这是另一个手动去混淆的版本,将所有初始化从表达式中移出到自己的语句中:
z='p="<"+"pre>"/* ,.oq#+ ,._, */;for(y in n="zw24l6k'
4e3t4jnt4qj24xh2 x/* =<,m#F^ A W###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^ A W###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
是一个包含所有代码的多行字符串。它是eval
编辑。 - 在代码末尾,
z
传递给setTimeout
。它的工作原理类似于requestAnimationFrame
和eval
在一起,以尽可能高的速率在间隔内对其进行评估。 - 代码本身初始化
p
,将附加HTML的字符串缓冲区,以及n
,一个base-36编码的数字数组(通过"4"
连接成一个字符串,注释是无关的垃圾,parseInt
不考虑)。 n
中的每个数字都编码一行(n.length == 16
)。现在枚举它。- 一堆变量被初始化,有些伪装成
e
数组文字,但它们在使用时被转换为数字(x
)或布尔值(r
)或字符串(t
)。 - 枚举数字
t
中的每个数字,每转一圈r
反转布尔值。对于不同的角度x
,并且根据当前时间new Date / 1000
(以便它给出动画),数组e
使用一些按位运算符填充 - 当r
为假时1
,当r
为真时2
s。 - 然后循环确实迭代图像的 61 列,从
x=0
到 122 列,以双步进行,将单个字符附加到p
。 -
B
反斜杠,字符串S
是根据代码字符串构建的,z
通过转义反斜杠和撇号,以获得它在源代码中的外观的准确表示。 - 每两个连续的数字
e
相加,用于访问" *#"
中的一个角色,以建立动画图像。如果未定义其中一个索引,则NaN
索引将解析为未定义的字符,而是从S
字符串中获取相应的字符(请查看公式x/2+61*y-1
)。如果该字符应为单词字符,则使用fontcolor
String 方法对其进行不同的着色。 - 在每一行之后,尾随的退格键和换行符被添加到
p
,HTML字符串被分配给文档正文。
如何为最小示例重写相同的效果?
下面是另一个示例:
setInterval(z='s=("setInterval(z=''"+'
z.replace(/['''''']/g,"''''$&")+"'')"'
).match(/.{1,37}/g).join("''''''n");d'
ocument.body.innerHTML="<''pre>"+s.sl'
ice(0, 175)+String( + new Date()).fon'
tcolor("red")+s.slice(188)')
它具有此类动画所需的所有相关内容:
动画的
setInterval
和Date
它自己的代码(类似奎因)的重建,在这里:
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>
元件输出将代码的某些部分替换为动画字符串
计算包含所有代码的字符串,超时使循环;该字符串存储在名为 z
的变量中,在代码的中间,在注释/*
和*/
之间有一个"地球 ASCII 艺术"。代码解析注释并更改文档内容,保留 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
}
- Javascript:selenium Web驱动程序isDisplayed()不工作
- jQuery UI自动完成突然停止工作
- AngularJS UI路由器不能像ng路由器那样工作
- HTML5音频加载和播放获胜'我不能在iPad上工作
- JavaScript打印功能使日历停止工作
- Javascript.getHours()工作不正常
- 为什么这在IE中的工作方式与在Firefox中不同
- 视频HTML没有'无法在Internet Explorer 11上工作
- 扩展移相器按钮类不工作
- Firebase迁移-简单的Firebase.set没有'不再工作了——旧的还是新的
- 谷歌地图不是以HTML显示,而是在JS Fiddle上工作
- 正在尝试使用if和else添加类,但无法正常工作
- Jquery FadeIn FadeOut 只工作一次
- Foreach无法在Typescript中工作
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- 为什么不是't窗口.恢复正常工作吗?(javascript/jquery)
- JS可以在Chrome中工作,但不能在Firefox中工作
- ajaxToolkit PopupControlExtender不工作.过时的
- HTML标记在脚本标记中工作
- 在JavaScript中的类中,push和concat的工作方式有何不同