Javascript eval - 混淆?

8

我发现了一些eval代码:

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

这段代码等于整数5。

这种类型的东西叫什么?我尝试在网上搜索,但似乎无法确定它被称为什么。我觉得这很有趣,想知道如何学习在输出不仅仅是整数5的情况下打印不同的东西,例如字母、符号等等。由于我无法确定代码中的模式,所以我尝试从中提取和添加内容来获得不同的结果,但是一直没有成功。

这是某种类型的混淆吗?


@thefourtheye 好的,我改口了 :-) - Mouser
我熟悉那种语言(指我见过/读过它)。这段 eval 代码是专门针对 JavaScript 的。除非我弄错了,而且很可能会,JavaScript 和 brainf*** 没有任何关系。Brainf*** 是一种除了娱乐外没有实际用途的奇异语言。虽然在这种情况下,对我来说,这个 eval 东西也纯粹是为了娱乐。也许还有一点知识。 - odran037
4个回答

10

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

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


4

这就是所谓的非字母数字 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]',
...

2
要得到值为5,表达式应该像这样。
+[!+[] + !+[] + !+[] + !+[] + !+[]]

让我们首先分析常见的元素。!+[]
  1. 在JavaScript中,空数组文字被视为Falsy。

  2. 应用于一个数组字面量的+运算符将尝试将其转换为数字,由于它是空的,JavaScript将其评估为0。

  3. 运算符将 0 转换为 true

所以,

console.log(!+[]);

会打印出true。现在,表达式可以简化为这样。

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

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

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

问题是关于这种技术的名称(如果有的话),而不是它如何或为什么起作用。 - Ixrec
没错,但还是很有帮助的。我没有把它看作是true+true..虽然我假设有一些方法来安排事情以得到数字5。或者任何数字都可以。那么问题就是如何获得其他整数、字母和符号。 - odran037

1
我不知道除了“滥用eval()”之外,有没有其他用于描述这种类型代码的术语。

我发现这非常有趣,想知道如何学习打印不同的东西,而不仅仅是整数5。字母、符号等等。由于我无法确定代码中的模式,因此我尝试添加和修改代码以获得不同的结果,但一直没有成功。

至少在这部分内容上,我可以部分回答。您所贴的eval()在很大程度上依赖于JavaScript奇怪的类型强制转换规则。网络上有很多页面描述各种奇怪的强制转换规则的后果,您可以轻松搜索到。但我找不到任何关于类型强制转换的参考,目的是从类似eval()的东西中获取“惊人”的输出,除非您计算this video by Destroy All Software(Javascript部分从1:20开始)。它们大多都着重于如何避免代码中的奇怪错误。对于您的目的,我认为我知道的最有用的东西是:
  • 逻辑非运算符会将任何东西转换为布尔值。
  • 一元正号运算符会将任何东西转换为数字。
  • 二元加号运算符在加法或连接之前强制将其参数转换为数字或字符串。通常,如果一个参数已经是字符串,它只会与字符串一起使用,但也有例外情况。
  • 按位运算符输出整数,无论输入是什么。
  • 转换为数字很复杂。布尔值将变为0或1。字符串将尝试使用parseInt(),如果失败则产生NaN。我忘记了其他的。
  • 将对象转换为字符串或数字将分别调用其"toString"或"toValue"方法(如果存在)。

你明白了吧。thefourtheye的答案详细介绍了这些规则如何应用于你提供的示例。我甚至不想尝试总结涉及日期、函数和正则表达式时会发生什么。

这是某种类型的混淆吗?

通常,你可以在代码缩小中免费获得混淆,所以我不知道为什么有人会在真实的生产代码中编写这样的代码(假设你是在那里找到它的)。


这很有帮助。不知道它叫什么或者它的相关信息,使得搜索和找到类似的东西变得困难。我记不得我在哪里找到它了。但我发现了这个网站:http://blog.mgechev.com/about/ 他的 eval 代码打印了他的名字。我也看不出为什么这会在生产中使用。 - odran037

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接