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

高级前端进阶

共 2323字,需浏览 5分钟

 ·

2020-07-11 20:18

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


我迫不及待打开了对应的网站,发现浏览器提示 No internet,这才发现因为我的动作太过于行云流水,电脑还没来得及连上 wifi  eaff14dcac3e6837f6d2a51fb79df62e.webp 29218681da038acef4ef087055355be5.webpFine,那就等 wifi 自己重连吧,等待的这段时间刚好回味一下 Chrome 自带的这款小恐龙游戏。科普:Chrome 浏览器是 Google 家的官方浏览器,使用体验全世界南波万。当用户在无网络时访问某一网址,浏览器会提示“无网络链接”(也就是上面这张图),按下空格键,就会唤醒一个小恐龙跑步刷分的游戏。如果在有网络连接时也想玩的话,可以直接在地址栏输入:chrome://dino


出于职业本身的敏感和好奇,我突然心生疑问:这应该是用 JS 做的吧?我顺势打开控制台,不如先看一下所有的全局变量? 8d5cea1144d8b58d4106c66fa8abfed4.webp239 个...太多了,我可没这个耐心 cd574ebc18feffa4ee814622d5a300f0.webp我停止了操作,开始思考这一切的可行性:
  1. 我在干什么?尝试自定义这个游戏
  2. 为什么要看全局变量?因为假设关于游戏的对象被暴露在了全局
  3. 如果没暴露在全局?行,那我就放弃了(周末的早晨我可不想在 sources 里面扒源码)
也就是说,如果没有在全局变量里找到那个对象,我就可以选择性放弃了。


再看一下上面这张图,不难发现,这 239 个全局变量,有很多都是老朋友了,name、history、location、onclick、onerror... 这些变量明显和这只小恐龙没啥关系,打印出来纯粹是来充个数,还浪费了我找目标的时间,所以我遇到了第一个问题:如何快速找到由开发者自定义的全局变量? 842c14ad209c0e55aa2541a45da8b7e1.webp假如我有一个正常的 window...不对,不用假如,新开一个空窗口不就得了 ef55951bfdb6bd4bc61b8a9044f78b49.webp 在新打开窗口的控制台,我得到了这样的结果: 0446b9ee67073f27c9435392a4d7f347.webp也就是说,在这个恐龙快跑的小游戏里,Google 的前端工程师向 window 注入了 43 个全局变量(239-196)... ad83a17de0637e826ad77e07d722aecb.webp怎么把这 196 个原生的全局变量拿过来呢?复制粘贴就太 low 了,让我想想... eb52b6dcffc07d5df404eb42c4264769.webp在原有窗口的基础上,再搞一个新窗口...这不就是 iframe 吗!iframe 虽然没有  window ,但是它有  contentWindow ,原则上来说,属性差别应该不大。所以现在只需要创建一个 iframe,拿它里面  contentWindow  的全局变量去过滤当前  window  的全局变量,就可以筛选出那多余的 43 个嫌疑人了。于是我在控制台敲出了下面这些代码 f66af5f98a8c9bb14c0111a9fd0595ec.webp回车! 9066a28e42d82793c223a4ef2b42f18e.webp诶,怎么是 45 个?比预期的多了 2 个,难道  window  里面还包含哪些  contentWindow  里面没有的变量吗?于是我把相同的代码拿去 url 为 about:blank 的窗口下执行了一遍,发现了罪魁祸首: 357a0c558bb59dcc7806cfb81c48ea05.webp哦...原来是我给 Chrome 安装的 React 开发者工具干的好事...忽略!我打开了先前检索到的 45(43+2) 个多余全局变量,大致扫了一眼,很快就发现了一个很可疑的选手: e897a2d0dfce560a1d5965c94f16c116.webp Runner ,不就是这个一直在跑步的小恐龙吗 ec287dcb02de47e50f85300a035d8fc6.webp看看它是个什么货色,无脑  typeof  一下: 8b9e60c30d4e03c41d90e46bc734c80f.webpemmm居然是函数,哦?函数,首字母还大写,这熟悉的味道,这不就是个构造函数吗!正所谓,构造函数的宝藏都在  prototype  里,在观察了一遍这个宝藏之后,我发现了一个名为  gameOver  的方法, b783c00c0b7688f7cb0c223680f20b46.webp这个函数名,难不成它就是那个让小恐龙去死的方法?既然这样,呵,我反手就把它用空函数覆盖了。于是...真的是...
8b4022f3fccc00230cad843cfdb8f0fa.webp然后我又发现了另一个有趣的方法: fcde7b8fdbedf7c5d9bf2e1ba0a60cc7.webp顾名思义,这是用来给小恐龙设置奔跑速度的方法,但是怎么调用呢?由构造函数创建的实例对象,可通过原型链访问构造函数 prototype 上的变量和方法,也就是说,如果能找到这个小恐龙对应的实例,那么就能直接调用这个  setSpeed  方法了。既然 Google 的前端工程师已经把这么多变量搞到全局了,那么...会不会也在全局存储了这个小恐龙实例?我重新审视了一遍那 43 个多出来的全局变量,并没有找到。我下意识地随手输入了一下这个  Runner  构造函数,真是山重水复疑无路柳暗花明又一村呐: b1c0e79119b8089f9ef0309db73da671.webp我甚至都不需要看  Runner  函数的全部代码,就知道原来实例被保存在一个名叫  instance_  的  Runner  自身属性里,论起好变量名的重要性,行,那我就不客气了,直接调用! 4e3fb79a703ab565ae41ebd3bd78f47d.webp于是...当我凝视着这个飞奔的无敌小恐龙时,我突然觉得...一切变得...
36c01312eff3ccb3f4b79fc69673c9ca.webp


支持

如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:


  1. 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)

  2. 关注我的官网 https://muyiy.cn,让我们成为长期关系

  3. 关注公众号「高级前端进阶」,公众号后台回复「面试题」 送你高级前端面试题,回复「加群」加入面试互助交流群


》》面试官都在用的题库,快来看看《《

浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报