前言
console.log((!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]); //sb
console.log(([][[]]+[])[+!![]] + ([]+{})[!+[]+!![]]); //nb
代码看起来是不是很神奇呢?是否可以输出任意的字母组合?带着这些问题来分析一下。
分析
JavaScript是弱类型的语言,上文示例中容易发现,打印的代码为单字母输出,均为从数组中取值,在C、Java等语言中,经常会有把一个整体转化为字符的case,在js则通过String.charAt
来完成,针对上文代码显然不合适,根据JavaScript的特性,组合一些关键字,结合''
的拼接,可以组合出以下 特殊字符串
和 数组下标
:
字符串/数字 | 表达式1 | 表达式2 | 表达式3 |
---|---|---|---|
“NaN” | (+{}+’’) | - | - |
“Infinity” | (+!![]/![]+’’) | (+!!{}/!{}+’’) | - |
“[object Object]” | ([]+{}) | ({}+’’) | - |
“false” | (!{}+’’) | (![]+’’) | - |
“true” | (!!{}+’’) | (!![]+’’) | - |
“undefined” | ([][[]]+’’) | ([][[]]+[]) | - |
0 | +![] | +!{} | +[] |
1 | +!![] | +!!{} | - |
2 | +!![]+!![] | !+[]+!![] | !+{}+!!{} |
可以看出,任意的 数组下标
都可以组合出来,对应的字符则需要从一些 特殊字符串
中,有 NaN
、Infinity
、 [object Object]
、 false
、 true
、undefined
,有16个小写字母 abcdefijlnorstuy
和3个大写字母 NIO
, 在这里面的单词均可以使用类似的代码编写;
这里需要了解另一个知识点,JavaScript中可以用下标获取到字符串中的单个字符,例如'true'[3]
对应的是字符 u
;
下面来看一些示例:
ufo
([][[]]+'')[+[]]+(![]+'')[+![]]+([]+{})[+!![]]
sos
[!+[]+!![]+!![]] + ([]+{})[+!![]] + (!{}+'')[!+[]+!![]+!![]]
lol
(![]+'')[!+[]+!![]] + ([]+{})[+!![]] + (![]+'')[!+[]+!![]]
alibaba
(![]+'')[+!![]] + (![]+'')[!+[]+!![]] + (+!![]/![]+'')[!+[]+!![]+!![]] + ([]+{})[!+[]+!![]] + (![]+'')[+!![]] + ([]+{})[!+[]+!![]] + (![]+'')[+!![]]
taobao
(!![]+'')[+[]] + (![]+'')[+!![]] + ([]+{})[+!![]] + ([]+{})[!+[]+!![]] + (![]+'')[+!![]] + ([]+{})[+!![]]
baidu
([]+{})[!+[]+!![]] + (![]+'')[+!![]] + (+!![]/![]+'')[!+[]+!![]+!![]] + ([][[]]+[])[!+[]+!![]] + ([][[]]+'')[+[]]
tencent
(!![]+'')[+[]] + (!![]+'')[!+[]+!![]+!![]] + ([][[]]+[])[+!![]] + ([]+{})[!+[]+!![]+!![]+!![]+!![]] + (!![]+'')[!+[]+!![]+!![]] + ([][[]]+[])[+!![]] + (!![]+'')[+[]]
toutiao
(!![]+'')[+[]] + ([]+{})[+!![]] + ([][[]]+'')[+[]] + (!![]+'')[+[]] + (+!![]/![]+'')[!+[]+!![]+!![]] + (![]+'')[+!![]] + ([]+{})[+!![]]
小结
JavaScript有太多的非常规代码,非常规的代码可以用来做一些代码的混淆,也算是一点点贡献,在很多混淆的代码中,会经常见到 void 0
的写法,等同于 undefined
,还有更多的case待发掘;
如有任何知识产权、版权问题或理论错误,还请指正。
转载请注明原作者及以上信息。