公众号关注 “GitHubPorn”

设为 “星标”,每天带你逛 GitHub!


Chrome 的小恐龙游戏,被我破解了...


一个阳光明媚的周末,透光的窗帘把我从睡梦中叫醒,大脑说今天是周六,可以慵懒个一上午,于是开心地打开我的 Mac 准备看两集 Rick and Morty 再起床洗漱。


我迫不及待打开了对应的网站,发现浏览器提示 No internet,这才发现因为我的动作太过于行云流水,电脑还没来得及连上 wifi Chrome 的小恐龙游戏,被我破解了...

Chrome 的小恐龙游戏,被我破解了...

Fine,那就等 wifi 自己重连吧,等待的这段时间刚好回味一下 Chrome 自带的这款小恐龙游戏。

科普:Chrome 浏览器是 Google 家的官方浏览器,使用体验全世界南波万。当用户在无网络时访问某一网址,浏览器会提示 “无网络链接”(也就是上面这张图),按下空格键,就会唤醒一个小恐龙跑步刷分的游戏。

如果在有网络连接时也想玩的话,可以直接在地址栏输入:chrome://dino




出于职业本身的敏感和好奇,我突然心生疑问:这应该是用 JS 做的吧?

我顺势打开控制台,不如先看一下所有的全局变量?

Chrome 的小恐龙游戏,被我破解了...

239 个… 太多了,我可没这个耐心Chrome 的小恐龙游戏,被我破解了...

我停止了操作,开始思考这一切的可行性:


  1. 我在干什么?尝试自定义这个游戏
  2. 为什么要看全局变量?因为假设关于游戏的对象被暴露在了全局
  3. 如果没暴露在全局?行,那我就放弃了(周末的早晨我可不想在 sources 里面扒源码)


也就是说,如果没有在全局变量里找到那个对象,我就可以选择性放弃了。




再看一下上面这张图,不难发现,这 239 个全局变量,有很多都是老朋友了,name、history、location、onclick、onerror… 这些变量明显和这只小恐龙没啥关系,打印出来纯粹是来充个数,还浪费了我找目标的时间,所以我遇到了第一个问题:如何快速找到由开发者自定义的全局变量?

Chrome 的小恐龙游戏,被我破解了...

假如我有一个正常的 window… 不对,不用假如,新开一个空窗口不就得了Chrome 的小恐龙游戏,被我破解了... 在新打开窗口的控制台,我得到了这样的结果:

Chrome 的小恐龙游戏,被我破解了...

也就是说,在这个恐龙快跑的小游戏里,Google 的前端工程师向 window 注入了 43 个全局变量(239-196)…

Chrome 的小恐龙游戏,被我破解了...

怎么把这 196 个原生的全局变量拿过来呢?复制粘贴就太 low 了,让我想想…

Chrome 的小恐龙游戏,被我破解了...

在原有窗口的基础上,再搞一个新窗口… 这不就是 iframe 吗!iframe 虽然没有  window ,但是它有  contentWindow ,原则上来说,属性差别应该不大。所以现在只需要创建一个 iframe,拿它里面  contentWindow  的全局变量去过滤当前  window  的全局变量,就可以筛选出那多余的 43 个嫌疑人了。

于是我在控制台敲出了下面这些代码

Chrome 的小恐龙游戏,被我破解了...

回车!

Chrome 的小恐龙游戏,被我破解了...

诶,怎么是 45 个?比预期的多了 2 个,难道  window  里面还包含哪些  contentWindow  里面没有的变量吗?于是我把相同的代码拿去 url 为 about:blank 的窗口下执行了一遍,发现了罪魁祸首:

Chrome 的小恐龙游戏,被我破解了...

哦… 原来是我给 Chrome 安装的 React 开发者工具干的好事… 忽略!

我打开了先前检索到的 45(43+2) 个多余全局变量,大致扫了一眼,很快就发现了一个很可疑的选手:

Chrome 的小恐龙游戏,被我破解了...

Runner ,不就是这个一直在跑步的小恐龙吗Chrome 的小恐龙游戏,被我破解了...

看看它是个什么货色,无脑  typeof  一下:

Chrome 的小恐龙游戏,被我破解了...

emmm 居然是函数,哦?函数,首字母还大写,这熟悉的味道,这不就是个构造函数吗!正所谓,构造函数的宝藏都在  prototype  里,在观察了一遍这个宝藏之后,我发现了一个名为 gameOver  的方法,

Chrome 的小恐龙游戏,被我破解了...

这个函数名,难不成它就是那个让小恐龙去死的方法?既然这样,呵,我反手就把它用空函数覆盖了。于是…

真的是…

Chrome 的小恐龙游戏,被我破解了...

然后我又发现了另一个有趣的方法:

Chrome 的小恐龙游戏,被我破解了...

顾名思义,这是用来给小恐龙设置奔跑速度的方法,但是怎么调用呢?由构造函数创建的实例对象,可通过原型链访问构造函数 prototype 上的变量和方法,也就是说,如果能找到这个小恐龙对应的实例,那么就能直接调用这个  setSpeed  方法了。既然 Google 的前端工程师已经把这么多变量搞到全局了,那么… 会不会也在全局存储了这个小恐龙实例?我重新审视了一遍那 43 个多出来的全局变量,并没有找到。我下意识地随手输入了一下这个  Runner  构造函数,真是山重水复疑无路柳暗花明又一村呐:

Chrome 的小恐龙游戏,被我破解了...

我甚至都不需要看  Runner  函数的全部代码,就知道原来实例被保存在一个名叫  instance_  的 Runner  自身属性里,论起好变量名的重要性,行,那我就不客气了,直接调用!

Chrome 的小恐龙游戏,被我破解了...

于是…

当我凝视着这个飞奔的无敌小恐龙时,我突然觉得… 一切变得…

Chrome 的小恐龙游戏,被我破解了...

---

爱分享,爱开源,GitHubPorn 现已正式上线!专注于为大家分享优质的计算机学习资源与开发者工具。

如果今天的推荐符合你的口味,请在文章点赞,以表示对我的支持,你们的点赞和转发关注,是我持续更新的动力^_^


Chrome 的小恐龙游戏,被我破解了...

原文始发于微信公众号(GitHubPorn):Chrome 的小恐龙游戏,被我破解了…