一個陽光明媚的周末,透光的窗簾把我從睡夢中叫醒,大腦說今天是周六,可以慵懶個一上午,于是開心地打開我的 Mac 準備看兩集 Rick and Morty 再起床洗漱。
我迫不及待打開了對應的網站,發現浏覽器提示 No internet,這才發現因為我的動作太過于行雲流水,電腦還沒來得及連上 wifi。
Fine,那就等 wifi 自己重連吧,等待的這段時間剛好回味一下 Chrome 自帶的這款小恐龍遊戲。
科普:Chrome 浏覽器是 Google 家的官方浏覽器,使用體驗全世界南波萬。當用戶在無網絡時訪問某一網址,浏覽器會提示“無網絡鍊接”(也就是上面這張圖),按下空格鍵,就會喚醒一個小恐龍跑步刷分的遊戲。
如果在有網絡連接時也想玩的話,可以直接在地址欄輸入:chrome://dino
出于職業本身的敏感和好奇,我突然心生疑問:這應該是用 JS 做的吧?
我順勢打開控制台,不如先看一下所有的全局變量?
239 個...太多了,我可沒這個耐心
我停止了操作,開始思考這一切的可行性:
也就是說,如果沒有在全局變量裡找到那個對象,我就可以選擇性放棄了。
再看一下上面這張圖,不難發現,這 239 個全局變量,有很多都是老朋友了,name、history、location、onclick、onerror... 這些變量明顯和這隻小恐龍沒啥關系,打印出來純粹是來充個數,還浪費了我找目标的時間,所以我遇到了第一個問題:如何快速找到由開發者自定義的全局變量?
假如我有一個正常的 window...不對,不用假如,新開一個空窗口不就得了
在新打開窗口的控制台,我得到了這樣的結果:
也就是說,在這個恐龍快跑的小遊戲裡,Google 的前端工程師向 window 注入了 43 個全局變量(239-196)...
怎麼把這 196 個原生的全局變量拿過來呢?複制粘貼就太 low 了,讓我想想...
在原有窗口的基礎上,再搞一個新窗口...這不就是 iframe 嗎!iframe 雖然沒有 window ,但是它有 contentWindow ,原則上來說,屬性差别應該不大。所以現在隻需要創建一個 iframe,拿它裡面 contentWindow 的全局變量去過濾當前 window 的全局變量,就可以篩選出那多餘的 43 個嫌疑人了。
于是我在控制台敲出了下面這些代碼
回車!
诶,怎麼是 45 個?比預期的多了 2 個,難道 window 裡面還包含哪些 contentWindow 裡面沒有的變量嗎?于是我把相同的代碼拿去 url 為 about:blank 的窗口下執行了一遍,發現了罪魁禍首:
哦...原來是我給 Chrome 安裝的 React 開發者工具幹的好事...忽略!
我打開了先前檢索到的 45(43 2) 個多餘全局變量,大緻掃了一眼,很快就發現了一個很可疑的選手:
Runner ,不就是這個一直在跑步的小恐龍嗎
看看它是個什麼貨色,無腦 typeof 一下:
emmm居然是函數,哦?函數,首字母還大寫,這熟悉的味道,這不就是個構造函數嗎!正所謂,構造函數的寶藏都在 prototype 裡,在觀察了一遍這個寶藏之後,我發現了一個名為 gameOver 的方法,
這個函數名,難不成它就是那個讓小恐龍去死的方法?既然這樣,呵,我反手就把它用空函數覆蓋了。于是...
真的是...
然後我又發現了另一個有趣的方法:
顧名思義,這是用來給小恐龍設置奔跑速度的方法,但是怎麼調用呢?由構造函數創建的實例對象,可通過原型鍊訪問構造函數 prototype 上的變量和方法,也就是說,如果能找到這個小恐龍對應的實例,那麼就能直接調用這個 setSpeed 方法了。既然 Google 的前端工程師已經把這麼多變量搞到全局了,那麼...會不會也在全局存儲了這個小恐龍實例?我重新審視了一遍那 43 個多出來的全局變量,并沒有找到。我下意識地随手輸入了一下這個 Runner 構造函數,真是山重水複疑無路柳暗花明又一村呐:
我甚至都不需要看 Runner 函數的全部代碼,就知道原來實例被保存在一個名叫 instance_ 的 Runner 自身屬性裡,論起好變量名的重要性,行,那我就不客氣了,直接調用!
于是...
當我凝視着這個飛奔的無敵小恐龍時,我突然覺得...一切變得...
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!