JavaScript 的内置字符串是什么?

这个问题很难用题目来概括

更新 我创建了一个 JSFiddle,它根据从这个问题中提取的字母从您的输入中构建一个模糊的字符串: 您可以访问它 给你,还是 大意更容易?

我最近在 这个侧写中遇到了一个有趣的混淆 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"

生成的其他字符串包括:

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

我想找一个替代“ n”和“[”的词,于是想到了这个:

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

我觉得这是在使用1和0的精神,但违反了原始代码的一个更优雅的方面,那就是与字符串没有任何关系的外观。还有人知道如何生成一个符合原始模糊代码的“ v”吗?

在许多有才华的 JavaScript 程序员对此进行了更深入的研究之后,我们发现了一些额外的信息

Firefox 返回“ I alone you”,原因如下:

([]+/-/[(!!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 返回“ I love you”,因为相同的代码返回:

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

在这个问题因为与“一个真正的编程问题”的可疑连接而结束之前,我想我应该添加一个基于 @ 超级快餐@ Cory 的@ alpha123’s的总结解决方案,请看:

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 引擎在告诉你它是多么的特别:)

14616 次浏览

下面是产生 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]

这将 n/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 的差异(显然 Firefox 将0开头的数字解析为八进制,而 Chrome 不这样做)在 Firefox 的情况下添加4,从而在两种情况下都从“本机”中获得“ v”(我找不到另一个“ v”: P)。
ParseInt 看起来有点不合适,但这是目前我能做的最好的工作了。

在 chrome 中,表达式 ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])的计算结果为 "function test() { [native code] }"[1^11<<1]的计算结果为23(按位运算符导致变量被截断为32位)

这给了 Chrome 一个 v:

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

火狐就是这么做的:

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

它们都是从 Object.prototype.preventExtensions()中提取出来的,所以您可能会找到一种跨浏览器的方法来引用该方法。(它是 Object 中唯一的17个字符的名称。初学者的原型。)

请随意建立一个更加模糊的版本,并把所有的功劳归于自己,我没有时间了;)

这差不多是我能得到的最接近的结果了,不幸的是,它违反了原始模糊处理的惯例,打电话给 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. 从一个包含单词“无效”的异常中获取文本

更新:

我开始玩代码高尔夫球,并一直使它更短,更换零件与更多的 1,等等。

对于 将军用例,如果字符大小写不是一个大问题,我可能倾向于作弊一点。

创建函数“ 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]}}}};

出于性能原因,如果需要,可以预缓存这些字母。

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"]

所以... 你的 翻译可能是 l[10+10+1]

或者,像这样的通用解决方案:

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"

为什么问题中没有使用 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 中使用。构建一个数组并使用 ==来确定浏览器。

[([]+/-/[(!!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)
]

首先,我要感谢杰森和所有的贡献者玩这个有趣的片段。我写这段代码 只是为了好玩是为了在2月14日把它发给我的妻子:)在笔记本电脑上只安装了 Chrome,我没有选择去检查它在 Firefox 和 IE 中是如何工作的。此外,我并没有真正期望内置方法的 toString()表示在其他浏览器中看起来会有所不同。

现在,转向真正的问题,让我们精确地看一下代码。是的,"v"是这里真正的“问题”。除了解析 [native code]字符串(可以从任何内置方法获取)之外,我找不到其他获取这个字母的方法。由于我限制自己没有字符串,除了使用 1以外没有数字,所以我需要利用一些只在名称中有可用字符的方法。

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

我分析了数组 []、对象 {}、正则表达式 /(?:)/、数字 1.1、字符串 "1"的不同内置方法,发现了 RegExp对象的一个漂亮的方法 {}4。它的名称可以由所有可用的字符组合而成,例如 true中的 "t""e",以及 {}1中的 {}0。我已经创建了一个字符串 {}2,并使用正则表达式文字 {}3的方括号表示法解决了这个问题,在这一行中已经正确识别:

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

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

function test() { [native code] }

如下:

function test() {
[native code]
}

在 IE 中:

 function test() {     [native code] }

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

所以,正如你清楚地看到的,我的代码从显示的字符串中获得第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]

然而,为了引起读者的兴趣,我不会提供一个解决方案。我真诚地相信你会很容易理解它是如何工作的... ... 有些人甚至可以用跨浏览器的方式给他们的爱人一个惊喜;)

附注 又一个混淆视听者

受到 Jason 创建一个通用混淆工具的想法的启发,我又写了一个。你可以在 返回文章页面 http://JSBin.com/amecoq/2找到它。它可以混淆任何包含数字 [0-9]、小拉丁字母 [a-z]和空格的文本。字符串的长度主要受到 RAM 的限制(至少我的答案的主体被成功地混淆了)。Chrome、 Firefox 和 IE 都支持该输出。

提示: 该工具使用了与上面提到的不同的模糊处理方法。