weixin_39652136
weixin_39652136
2020-11-28 23:00

从hello world看JavaScript隐藏的黑魔法

写在最前

事情的起因是这段看起来不像代码的代码:

_20170825232240

有兴趣的同学可以自己先尝试下!


([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[+[]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+([]+{})[+!![]]+(!![]+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+[])+(+!![]+[]))

作者对着这段代码足足看了一下午,我只想说这不是什么深奥的黑魔法。一点点看下来你就知道其中的原理了。最后会有一段作者自己封装的代码叫nb.js(源码在这里),它实现了输入数字字母后自动生成这种玄学代码片段。就像这样:

_20170825233827

欢迎关注我的博客,不定期更新中——

JavaScript小众系列开始更新啦

——何时完结不确定,写多少看我会多少!这是已经更新的地址: - 小众系列之按位非运算符:JavaScript中奇特的~运算符 - 小众系列之终极类型转换:从hello world看JavaScript隐藏的黑魔法制 - 小众系列之隐式类型转换:从[] == ![]看隐式强制转换机制 - 小众系列之事件循环:从HTML5与PromiseA+规范来看事件循环

这个系列旨在对一些人们不常用遇到的知识点,以及可能常用到但不曾深入了解的部分做一个重新梳理,虽然可能有些部分看起来没有什么用,因为平时开发真的用不到!但个人认为糟粕也好精华也罢里面全部蕴藏着JS一些偏本质的东西或者说底层规范,如果能适当避开舒适区来看这些小细节,也许对自己也会有些帮助~文章更新在我的博客,欢迎不定期关注。

转换思路

基础思路:通过关键字来获取字母

什么意思?比如:f。看到f你会想到哪个关键字?同时这个关键字是要在类型转换的机制下能够被打印出来的。如果类型转换你还不是很了解,可以先读下这篇来理解一下:从[] == ![]看隐式强制转换机制。我相信很多同学可以想到是

false
这个关键字。那么我们的思路就有了也就是要让代码实现
'false'[0]
这件事,这个认识统一之后我相信下面的代码一定不难理解了:

[[[] == []] + []][+![]][+![]]
//过程理解为
[] == [] => false
[[] == []] => [false]
[[[] == []] + []] => ['false'], [+![]] => [0]
[[[] == []] + []][+![]] => 'false'
[[[] == []] + []][+![]][+![]] => 'false'[0] => 'f'

其中大体形式可以理解为:['false'][0][0] => 'f'

是不是瞬间觉得也不过如此?

可通过关键字获取的字符

当你知道可以用上面的方式来获取自己需要的字母之后,接下来要做的是思考一下你能从关键字中获取哪些字母呢,作者总结了以下你可以通过关键字获得的字母:


([][[]]+[]) => 'undefined'
+[1+[[][0]+[]][0][3]+400][0]+[] => 'Infinity'
[[[] == []] + []][+![]] => 'false'
[[[] != []] + []][+![]] => 'true'
([]+{}) => "[object Object]"

感兴趣的同学自己打印下就明白为什么了。

接下来要说的是剩下的字母怎么办?当然了你仍然可以通过试图寻找关键字的方式来获取字母。但是如果标点我也想要呢?或者说26个字母我都想要怎么办? 具体点来说对于“hello world!”这段字符串来看,至少“w”,"!"的获取方法通过关键字的形式我们是无从下手的。

unescape

unescape() 函数可对通过 escape() 编码的字符串进行解码。但是已经废弃了

是的现在已经不建议如此使用了,但是浏览器下基本还是支持这个函数的。通过这个函数我们可以通过ascll码来直接得到我们需要的字符:


unescape('%77') => 'w'

如此看来,除了我们可以快速得得到一些关键字字母外,用这个方法我们便可以实现任意字母的组合。而作者封装的nb.js也是基于这两者来实现输出黑魔法字符串的。

那么现在的问题是如果通过字符串来执行

unescape('%77')
这段代码?

来看下hello world那段代码是如何实现的:

在这里也不绕弯子了,作者打印了很多次之后才发现是如此调用的:


[]['sort']['constructor']('return unescape')

因为JS调用方法不光是“.”调用,通过[]也是可以调用的。同时通过return unescape,返回了一个匿名函数形成了闭包。故调用的时候采用如下方式:


[]['sort']['constructor']('return unescape')()('%77') => 'w'

至于为什么这段代码写出来如此长是因为上面的每一个字母都是一点点拼出来的,也行好上面通过关键字的方式可以得到这些字母=。=不然的话——

封装nb.js

所以经过上面的分析你会发现,除了字符串长度感人之外,这种通过拼接字符串可以返回函数并且执行的方式还真是蛮炫酷的。为了达到装逼的效果。作者决定封装一个支持字母和数字的函数,当你传入普通的字符串之后,会返回带有黑魔法气息的冗长字符串,尽情拿去装x吧,不客气~

封装过程

维护基础对象与ascll表对象


var baseAlibrary = {
    'a': '[[[] == []][0]+[]][0][1]',
    'b': null,
    'c': '[[][[[][0] + []][0][4]+[[][0] + []][0][5]+[[][0] + []][0][1]+[[][0] + []][0][2]]+[]][0][3]',
    'd': '([][[]]+[])[+!![]+!![]]',
    'e': '([][[]]+[])[+!![]+!![]+!![]]',
    'f': '([][[]]+[])[+!![]+!![]+!![]+!![]]',
    'g': null,
    ...
    '0': '(+![])',
    '1': '(+!![])',
    '2': '(+!![]+!![])',
    ...
    ',': null,
    '!': null,
    }
    var ascll = { //ascll表可自行配置, 新添加后需要在上面对象中配置相同key,只是value为null
        'A': '41',
        'B': '42',
        ...
    }

将简单的字母转换方式直接存储下来,如果需要的字符无法从基础对象获取,就记为null,并在ascll表中写入相关转码方式。

封装unesacpe


var result = ''
    var unescapeStr = '[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])'
    //将[]['sort']['constructor']('return unescape')的黑魔法形式存储起来之后直接调用
    function changeAscll(ascllItem) {
        var ascllResult = ''
        var middleValue = ''
        ascll[ascllItem].split('').forEach(function(item) {
            if(isNaN(item)) { //ascll中遇到字母则需要再次进行unescape转码
                var str = ''
                ascll[item].split('').forEach(function(data) {
                    str += '+[' + baseAlibrary[data] + ']'
                })
                middleValue += '+' + unescapeStr + '()('+ baseAlibrary['%']+'+' +  str.slice(1) + ')'
            } else {
                middleValue += '+[' + baseAlibrary[item] + ']'
            }   
        })
        ascllResult += '+' + unescapeStr + '()('+ baseAlibrary['%']+'+' +  middleValue.slice(1) + ')'
        return ascllResult
    }
    function getUnEscape(str) {

    }
    strArr.forEach(function(item) {
        Object.keys(baseAlibrary).forEach(function(obj, i) {
            if(item.toLocaleLowerCase() === obj) {
                if(!baseAlibrary[item]) {
                    Object.keys(ascll).forEach(function(ascllItem) {
                        if(obj === ascllItem) {
                            var cbValue = changeAscll(ascllItem).slice(1)
                            result += '+' + cbValue
                        }
                    })
                } else {
                    result += '+' + baseAlibrary[obj]
                }
            }
        })
    })
    console.log(result.slice(1))

效果

也就是一开始大家看到的: _20170825233827

作者将函数绑定在了this上,通过

this.reallyNb()
即可得到你想要的~

PS:代码请部署在服务器中再打开页面,否则个别字母通过location方法会取不到,主要就是t,p。不过这个问题之后作者会将其以ascll表的方式存储,就没有环境限制了。只是作者嫌弃那样做打印的字符串太长了~

最后

不定时更新中—— 有问题欢迎在issues下交流。

该提问来源于开源项目:Aaaaaaaty/blog

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

12条回答

  • weixin_39530838 weixin_39530838 4月前

    已经找到解决方案。 在执行类似于这样的代码,时 0 提示“unescaoe is not defined”, 我给它定义一个对象, 执行【var unescaoe = unescape】 1 又提示,再定义一个对象,【var escaoe = escape】 2 再执行,有了。 3

    点赞 评论 复制链接分享
  • weixin_39530838 weixin_39530838 4月前

    这看起来很简单,也很基础,但很有效,很能解决问题

    点赞 评论 复制链接分享
  • weixin_39652136 weixin_39652136 4月前

    👍

    点赞 评论 复制链接分享
  • weixin_39984442 weixin_39984442 4月前

    2018-04-09 1 52 14

    点赞 评论 复制链接分享
  • weixin_39984442 weixin_39984442 4月前

    [+![]] => 0 应该是 [+![]] => [0]

    点赞 评论 复制链接分享
  • weixin_39652136 weixin_39652136 4月前

    已修正 感谢指出

    点赞 评论 复制链接分享
  • weixin_39536806 weixin_39536806 4月前

    image

    现在浏览器已经不支持unesacpe了

    点赞 评论 复制链接分享
  • weixin_39652136 weixin_39652136 4月前

    嗯嗯我提到了 确实是废弃的不过之前还是有版本可以支持的 纯属娱乐哈哈哈

    点赞 评论 复制链接分享
  • weixin_39984442 weixin_39984442 4月前

    你截图里是 unescaoe,浏览器都还是支持 unescape 的。 想知道 % 是怎么来的啊

    点赞 评论 复制链接分享
  • weixin_39536806 weixin_39536806 4月前

    你的chrome是什么版本的,我刚试是不行的 unescaoe is not defined

    点赞 评论 复制链接分享
  • weixin_39984442 weixin_39984442 4月前

    Chrome/65.0.3325.181

    点赞 评论 复制链接分享
  • weixin_39536806 weixin_39536806 4月前

    我的也是 给个截图哈 我看看你咋调用的

    点赞 评论 复制链接分享