Javascript eval - 混淆?

Javascript eval - obfuscation?

我遇到了一些评估代码:

eval('[+!+[]+!+[]+!+[]+!+[]+!+[]]');

此代码等于整数 5。

这种东西叫什么?我试过在网上搜索,但我似乎无法弄清楚这指的是什么。我觉得这很有趣,想知道 where/how 一个人学习如何打印不同的东西,而不仅仅是整数 5。字母、符号等。因为我无法在该代码中指出一个模式,我已经从中获取并添加到它以产生不同的结果有 0 个成功。

这是某种混淆吗?

要得到 5 的值,表达式应该是这样的

+[!+[] + !+[] + !+[] + !+[] + !+[]]

我们先分析一下共同的要素。 !+[].

  1. JavaScript 中的空数组文字被视为 Falsy。

  2. + 运算符应用于数组文字,将尝试将其转换为数字,并且由于它为空,JavaScript 会将其计算为 0。

  3. ! 运算符将 0 转换为 true.

所以,

console.log(!+[]);

将打印 true。现在,表达式可以像这样减少

+[true + true + true + true + true]

由于true在算术表达式中被视为1,实际表达式变为

+[ 5 ]

+ 运算符尝试将数组 ([ 5 ]) 转换为数字,结果为 5。这就是为什么您得到 5.

除了 "abusing eval()".

之外,我不知道有什么术语可以用来描述这种类型的代码

I find this very interesting and would like to know where/how one learns how to print different things instead of just the integer 5. Letters, symbols and etc. Since I can't pin point a pattern in that code I've had 0 success taking from and adding to it to make different results.

这部分我至少可以部分回答。您粘贴的 eval() 在很大程度上依赖于 Javascript 的奇怪类型强制规则。网络上有 很多 页面描述了强制规则的各种奇怪结果,您可以轻松搜索这些页面。但是我找不到任何关于类型强制的参考,具体目标是从 eval() 之类的东西获得 "surprising" 输出,除非你算上 this video by Destroy All Software(Javascript 部分从 1:20).可以理解,他们中的大多数都关注如何避免代码中出现奇怪的错误。为了您的目的,我相信我所知道的最有用的东西是:

  • !运算符会将任何内容转换为布尔值。
  • 一元 + 运算符会将任何内容转换为数字。
  • 二进制 + 运算符将在添加或连接它们之前将其参数强制转换为数字或字符串。通常只有当一个或另一个参数已经是一个字符串时,它才会与字符串一起使用,但也有例外。
  • 无论输入如何,按位运算符都输出整数。
  • 转换为数字很复杂。布尔值将变为 0 或 1。字符串将尝试使用 parseInt(),如果失败则生成 NaN。其他的我忘了。
  • 将对象转换为字符串或数字将分别调用其 "toString" 或 "toValue" 方法(如果存在)。

你懂的。 thefourtheye 的回答详细介绍了这些规则如何应用于您给出的示例。我什至不打算尝试总结涉及日期、函数和正则表达式时会发生什么。

Is this some type of obfuscation?

通常情况下,作为缩小的一部分,您会免费获得混淆,所以我不知道为什么有人会在实际生产代码中编写它(假设您是在那里找到它的)。

这称为 非字母数字 JavaScript,这可能是因为 JavaScript 类型强制转换功能。实际上有一些方法可以调用 eval/Function 而不必使用字母字符:

[]["filter"]["constructor"]('[+!+[]+!+[]+!+[]+!+[]+!+[]]')()

将字符串 "filter" 和 "constructor" 替换为非字母数字表示后,您将获得完整的非字母数字 JavaScript.

如果你想玩这个,有一个网站可以做到:http://www.jsfuck.com/

检查此 https://github.com/aemkei/jsfuck/blob/master/jsfuck.js 以获取更多示例,如下所示:

'a':   '(false+"")[1]',
'b':   '(Function("return{}")()+"")[2]',
'c':   '([]["filter"]+"")[3]',
...

除了 eval() 之外,这种类型的混淆被称为非字母数字混淆。 要完全非字母数字,eval 必须由 Array 构造函数原型函数和下标符号执行:

[]["sort"]["constructor"]("string to be evaled");

然后将这些字符串转换为非字母数字形式。

据我所知,它是由 Yosuke Hosogawa 于 2009 年左右首次提出的。 如果您想实际查看它,请查看此工具:http://www.jsfuck.com/

它不被认为是一种好的混淆类型,因为它很容易逆向回到原始源代码,甚至不必 运行 代码(静态)。另外,它极大地增加了文件大小。

但它是一种有趣的混淆形式,用于探索 JavaScript 类型强制转换。要了解更多信息,我推荐此演示文稿,幻灯片 33: http://www.slideshare.net/auditmark/owasp-eu-tour-2013-lisbon-pedro-fortuna-protecting-java-script-source-code-using-obfuscation