JavaScript的内置string是什么?

这个问题很难在题目中总结

更新我创build了一个JSFiddle,基于从这个问题中提取的字母,从input中生成一个模糊的string:你可以在这里访问它,或者一个要点会更容易吗?

我最近在这个configuration文件中遇到了一些模糊的JavaScript,看起来像这样:

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!- [])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1 +[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+([,][ ~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+ 1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1] 

抱歉毁了惊喜,但当这个评估它返回这个:

 "I love you" in Chrome "I lone you" In Firefox "I lo[e you" in IE10 

这种方式在发生的时候会产生一系列的消息,像这样(用“I”作为例子)从中拉出字母:

 []+1/!1 returns "Infinity" then [[]+1/!1] creates this array: ["Infinity"] then [[]+1/!1][1^1] Takes the first (1^1 == 0) element of that array "Infinity" finally [[]+1/!1][1^1][1>>1] Takes the first (1>>1 == 0) char of that string "I" 

其他生成的string包括:

 ({}+[]) -> "[object Object]" (where the space comes from) ([]+!!-[]) -> "false" (used for it's "l") [/~/+{}][+!1] -> "/~/[object Object]" (this is used for an "o") (/<</[1]+[]) -> "undefined" 

我有兴趣find替代“n”和“[”,并提出这个:

 String.fromCharCode(('1'.charCodeAt(0)<<1)+(10<<1)) 

我觉得我本着使用1和0的精神,但是违反了原来代码中更优雅的一个方面,即与string无关的外观。 其他人有没有想法如何生成一个“V”,以保持原来的混淆代码?

这里有一些额外的信息是在许多有才华的JavaScript程序员深入研究之后发现的

火狐返回“我孤单你”由于这一行:

 ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+ 

[1^11<<1]从这里修剪一个特定的字符:

 ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]) 

其中评估如下:

 "function test() { [native code] }" 

看起来我们可能有我们的“V”!

Chrome返回“我爱你”,因为相同的代码返回这个:

 "function test() { [native code] }" 

在这个问题closures之前,由于“真正的编程问题”,我想我会添加一个基于@ Supr , @ Cory和@ alpha123的概括解决scheme。

 alert([[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+( []+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+[([]+/-/[( !!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+( !!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[ ])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[ ])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[ ])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11 +1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<< 1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1 )+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>> 1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1 ]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]+([,][~1]+[] )[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+ (/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</ [1]+[])[1/1.1&1]) 

鉴于代码的复杂性和它产生的消息,它几乎就像JavaScript引擎告诉你有多特别:)

首先,我要感谢Jason和所有的贡献者玩这个有趣的片段。 我已经写了这段代码只是为了好玩 ,以便在2月14日发送给我的妻子:)只有Chrome安装在笔记本电脑上我没有select检查它是如何工作在Firefox和IE浏览器。 此外,我还没有真正地预料到,在其他浏览器中,内置方法的toString()表示可能会有所不同。

现在, 转到真正的问题 ,让我们看看代码。 是的, "v"是真正的“问题”在这里。 除了parsing[native code]string,我发现没有其他的方式来获得这个字母,可以从任何内置的方法。 由于我限制自己没有string和除了1使用的号码,我需要利用一些只有名字中可用字符的方法。

可用的字符可以从现有的关键字和string表示中获得,也就是从一开始我们有NaNnullundefinedInfinitytruefalse"[object Object]" 。 其中一些可以很容易地转换为string,例如1/!1+[]给出"Infinity"

我已经分析了数组[] ,对象{} ,正则expression式/(?:)/ ,数字1.1 ,string"1"不同的内置方法,并且发现了一个名为test()RegExp对象的一个​​漂亮的方法。 它的名字可以从所有可用的字符组合而来,例如"t""e"来自true ,而"s"来自false 。 我已经创build了一个string"test"并使用方括号标记正则expression式/-/在本行中正确标识了这个方法:

 /-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]] 

正如已经讨论过的,这段代码在Chrome中被评估为:

 function test() { [native code] } 

在Firefox中:

 function test() { [native code] } 

并在IE中作为:

  function test() { [native code] } 

(后者要特别注意function关键字前的空格)

所以,正如你清楚地看到的,我的代码是从显示的string中获得第24个字符,在Chrome中是"v" (按计划),但不幸在Firefox和IE中分别是"n""["

为了在所有浏览器中输出相同的结果,我使用了不同于其他答案中所示的方法 。 现在修改后的版本如下所示:

 javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!- [])[1<<1]+[/~/+{}][+!1][-~1<<1]+/\[[^1]+\]/[([]+![])[1<<1<< 1]+(/|/[(1+{})[1+11>>>1]+[[]+{}][+!1][1]+([]+1/[])[1<<1>>1] +([1<1]+[])[1+11>>>1+1]+[[!!1]+1][+[]][1-1]+([]+!!/!/)[1|1] +(/1/[1]+[])[!1%1]+(-{}+{})[-1+1e1-1]+(1+[!!1])[1]+([]+1+{} )[1<<1]+[!!/!!/+[]][+[]][1&1]]+/=/)[1e1+(1<<1|1)+(([]+/-/[( !!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1 ]])[1^1]==+!1)]+(!![]+{})[1|1<<1]+[1+{}+1][!1+!1][(11>>1)+1 ]](([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+ (!!1+[])[1^1]]))[1&.1][11>>>1]+([,][~1]+[])[1-~1]+[[]+{}][! 1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[] ,[]+{}][1<<1>>>1][1||1]+(/[<+>]/[1&1|1]+[1.1])[1/11.1&1.11] 

然而,为了吸引读者,我不会提供解决scheme。 我真的相信你会很容易理解它是如何工作的……有些甚至可以用浏览器的方式让他们心爱的人惊讶;)

PS 另一个混淆器

受Jason的想法的启发,我创build了一个通用的混淆工具,我又写了一个。 你可以在JSBinfind它: http : //jsbin.com/amecoq/2 。 它可以混淆包含数字[0-9] ,小拉丁字母[az]和空格的任何文本。 string的长度主要受限于你的RAM(至less我的回答正文是成功混淆)。 Chrome,Firefox和IE支持输出。

提示:该工具使用了与上面介绍的不同的混淆方法。

为什么不是使用问题的native code位? 这个在Chrome和Firefox中都给出了一个'v'

 ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]>([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]?([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1] 

编辑支持IE浏览器,并没有三元运算符:这个工程在Chrome,IE和FF。 build立一个数组,并使用==来确定浏览器。

 [([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)] 

读:

 [ //ie ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)], //ch ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1], //ff ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1] ] [ //ch? ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+ //ff? ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1) ] 

这跟我所能得到的差不多,不幸的是,它通过调用unescape()来违反原始混淆的约定:

 unescape((/%/+[])[1]+(/1/[1]+[])[1%1]+(+!1)+(+!1)+(1e1+(11*(1-~1)<<1))) 

拆除:

 (/%/+[])[1] => "%" (/1/[1]+[])[1%1] => "u" (+!1) => "0" (+!1) => "0" (1e1+(11*(1-~1)<<1)) => "76" =========================== unescape("%u0076") => "v" 

其他想法:

  1. 以某种方式得到unescape("\x76")
  2. 以某种方式转换118而不调用String.fromCharCode()
  3. 从exception中获取文本中的“无效”字样

更新:

我开始打高尔夫球,并且缩短了比赛时间,更换了更多的部分,等等。

以下是生成n / v的部分:

 ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1] 

在Firefox中, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])计算结果为

 "function test() { [native code] }" 

而在Chrome中是这样的

 "function test() { [native code] }" 

1^11<<1等于23.所以由于Firefox的额外空白,这不足以达到'v',而是'n'。

这就是为什么你不应该依赖Function#toString行为。 ;)

编辑:最后,我发现了一个合理的混淆跨浏览器版本:

 [[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]+([,][~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1] 

这将replacen / v部分:

 ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)] 

它利用parseInt中的差异(显然Firefoxparsing数字以0开头为八进制,而Chrome不)在Firefox的情况下添加4,从而在两种情况下从“native”获得“v”(我找不到另一个“v ':P)。
parseInt看起来有点不合适,但这是我现在可以做的最好的。

对于一般用例来说,如果angular色包装不是一个大问题,我可能会倾向于作弊一点。

创build函数“c”,将数字0 .. 25变成一个字符。

 c=function(v){for(var i in window){for(var ci in i){if(parseInt(i[ci],(10+11+11)+(1<<1)+(1<<1))==(v+10)){return i[ci]}}}}; 

出于性能原因,如果需要,请预先caching字母。

 l=[];for(var i=0; i<(11+11)+(1<<1)+(1<<1);i++){l[i]=c(i);} 

在Chrome控制台中,生成的数组如下所示:

 > l; ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "K", "l", "m", "n", "o", "p", "q", "r", "S", "t", "u", "v", "w", "x", "y", "Z"] 

所以…你的v可能是l[10+10+1]

或者,像这样的一般解决scheme:

 p=(function(){10%11}+[])[1+11+(1<<1)]; // "%" u=(function(){club=1}+[])[1+11+(1<<1)]; // "u" vc=p+u+(0+[])+(0+[])+((111>>1)+11+10+[]); // "%u0076" unescape(vc); 

或者,对于这个特定的问题,也许只是:

 (function(){v=1}+[])[10+(1<<1)]; // "v" 

这在Chrome中提供了av:

 Object.getOwnPropertyNames(Object)[17][3]; 

这在Firefox中是这样的:

 Object.getOwnPropertyNames(Object)[9][3] 

他们都把它从Object.prototype.preventExtensions() ,所以你可能find一个跨浏览器的方式来引用该方法。 (对于初学者,这是Object.Prototype中唯一的17个字符的名字。)

随意构build一个更加模糊的版本,并为自己所有的功劳,我没时间了;)

在chrome中,expression式([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])计算为"function test() { [native code] }"[1^11<<1]评估为23(按位运算符导致variables被截断为32位)