含有二进制值的混淆JavaScript代码?

12

这段代码输出 D。问题是为什么会输出D?

alert([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[+!+[]]](+[]+[+[]])[+!+[]]);

我理解![]被转换为false0等值,但是它是如何执行的?以及如何将其转换为人类可以理解而不仅仅是Jon Skeet?

有人能够分解一些代码并解释发生了什么吗?


1
哇,这太棒了。我想看一下这个的性能分析。 - Yuval Adam
3
@Yuval,这个东西的性能当然是真的差:http://jsperf.com/cryptic-obfuscation ;) - Christian C. Salvadó
3个回答

11

好的,分部分评估这个表达式,最终等价于:

[]['sort']['call']()["btoa"]("00")[1]; // "D"

可以简化为:

btoa("00")[1]; // "D"

如何“解码”它?

只需检查使用的运算符,例如,我们首先可以看到使用了数组文字,然后进行了几个方括号符号表示的属性访问和一些调用。

它是如何工作的?

诀窍是链接多个类型转换,例如,要获取字母f

(![]+[])[+[]]
如果我们观察括号里的第一部分![]+[],我们会看到一个布尔反转,它将返回false,因为数组对象始终是真值,然后是字符串连接。

这产生了字符串"false",然后,在第二部分中,我们看到应用于该字符串的方括号,以访问一个字符,并且表达式+[]的结果为0

+[]会给出零,因为空数组的toString方法返回一个空字符串,而当将其转换为数字时(在此示例中使用一元的+ 运算符),空字符串会转换为零。

这只是一些技巧,像"true""false""null""undefined"等可以生成字符串的东西,还有更多技巧可以得到数值。

例如,要获取一个数字-访问一个字符-,他们再次使用神秘的类型转换:

+[];            // 0, equivalent to +""
+!+[];          // 1, equivalent to +true
!+[]+!+[];      // 2, equivalent to +true+true
!+[]+!+[]+!+[]; // 3, equivalent to +true+true+true

你是如何得到它的?有没有工具可以将这段代码转换? - BrunoLM
5
在交互式的Javascript shell中尝试不同的部分(内置于Chrome和IE8中,并可在Firefox中获取Firebug插件,或安装Node.js或其他工具)。 - einarmagnus
2
谢谢。我现在明白它是如何工作的了。但我仍然想知道你是如何这么快解决它的 :P - BrunoLM

4

它使用javascript类型转换做一些技巧。正如CMS所指出的那样,它相当于:[]['sort']['call']()["btoa"]("00")[1];

他们通过从false等中提取字符串来构建字符串。

例如,要获取“sort”中的s

获取一个“false”:(![]+[]) -- ![]返回false,+[]将其转换为字符串。

使用!+[]+!+[]+!+[]获取值3-每个!+[]返回true,但是当您添加布尔值时,您会得到一个整数表示。例如:true + true = 2

使用字符串索引访问符号("false"[3] = 's')获取s(![]+[]) [!+[]+!+[]+!+[]]

现在你有了一个s。他们不断这样做,直到他们有足够的内容来访问他们想要的任何方法或属性。


1

![]是假的。 ![] + []评估为“false”。+[]是0,因此!+[]是真的,等等。 JavaScript在其隐含类型转换方面非常奇怪。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接