JavaScript(ECMAScript6),每行2个字节
'\
'[
'\
b\
i\
g'
][
'\
c\
o\
n\
s\
t\
r\
u\
c\
t\
o\
r'
][
'\
c\
a\
l\
l'
](
0,
`\
n\
=\
p\
r\
o\
m\
p\
t\
(\
'\
'\
)\
;\
i\
=\
0\
;\
f\
o\
r\
(\
;\
+\
+\
i\
<\
=\
n\
;\
c\
o\
n\
s\
o\
l\
e\
.\
l\
o\
g\
(\
i\
%\
5\
?\
f\
|\
|\
i\
:\
f\
+\
'\
P\
i\
e\
'\
)\
)\
f\
=\
i\
%\
3\
?\
'\
'\
:\
'\
A\
p\
p\
l\
e\
'\
`)
()
详细说明
我们可以使行更短的方法是将代码转换为字符串并转义行尾,这将限制每行2个字节。
所以alert(1)
变成
"\
a\
l\
e\
r\
(\
1\
)"
但是现在您的代码是一个字符串,因此我们需要将字符串作为代码执行。我知道至少有四种方法可以将字符串作为代码执行:
- 评估(代码)。至少要调用5个字节
eval(
- setTimeout(代码,超时)。异步运行函数,但是(可选)如果您传递字符串,它将在内部调用eval。
- 您可以利用DOM并将代码放入
onclick=""
属性中,但是我无法使元素创建部分简短。
- 调用Function构造函数new Function()将把您的代码解析为一个匿名函数,您以后可以调用该函数(我使用了此函数)。
所有本地函数里面生活的窗口对象,并在JavaScript中,您可以访问使用对象属性点符号,以便eval()
成为window.eval()
,或者您也可以访问使用属性括号标记 window['eval']()
。您可以利用此eval
方法使用前面介绍的方法将in分成多行。但是您仍然必须键入window,一个技巧是,如果您不在框架内,则top变量也是window,因此window.eval变为top.eval(少3个字节)。
w=top
w['eval']
You can shorten the assignment using parenthesis
w=(
top
)
w[
'e\
av\
al'
](
/*string*/
)
因此,这将使代码最少3个字节。为了使代码为2个字节,我使用了new Function(/*string*/);
构造函数,但是我必须要创造性地访问它而不必键入它。
首先,Function构造函数允许您省略new关键字来作为函数调用它,这减少了4个字节,但由于另一个原因,它也很重要。调用构造函数的函数仍然返回一个实例,这允许我们转向new Function(code)
到Function(code)
。另一个重要的事情是Function构造函数有一个call
方法,可以使您调用任何函数,但可以覆盖此引用,而Function构造函数本身是一个函数,您可以像调用self一样对其上的方法进行调用Function.call(null, code)
。
所有本机函数都是Function构造函数的实例,而javascript中的所有对象都具有构造函数属性。因此,您可以访问任何本地函数(例如)上的Function构造函数alert.constructor
,并使用调用方法可以将构造函数作为函数执行。现在,我们有alert.constructor.call(null,code)返回一个函数。
结合之前的理论,我们可以将其转变为 alert['constructor']['call'](null, code)
现在我们只需要找到一个简短的命名函数或方法,所以我在String构造函数中选择big()方法。所以我可以直接从空字符串访问它"".big
"".big.constructor.call(null, "code")();
''['big']['constructor']['call'](0,'/* code */')()
然后我把所有东西都弄碎了2个字节
短儿的解释(TLDR)
我正在访问新的Function(code)构造函数来解析字符串,而不是eval(code)。可以通过执行anyFunction在每个本机函数上使用此构造函数。构造函数,例如alert.constructor===Function
。我在String.prototype.big中 使用函数/方法,String.prototype.big.constructor.call(null, /*string*/)
但是直接从字符串文字访问它"".big
,并将其转换为方 括号。""['big']['constructor']['call'](0, CODE)
才能使用打破它\
。