丨JavaScript 逆向過程中無限 Debug 的繞過方案

語言: CN / TW / HK

這是「進擊的Coder」的第  608  篇技術分享

作者:崔慶才

在做爬蟲的時候,我們經常會在程式碼裡面遇見 debugger 這麼一個關鍵字。 debugger 是 JavaScript 中定義的一個專門用於斷點除錯的關鍵字,只要遇到它,JavaScript 的執行便會在此處中斷,進入除錯模式。

有了 debugger 這個關鍵字,我們可以非常方便地對 JavaScript 程式碼進行除錯,比如使用 JavaScript Hook 時,我們可以加入 debugger 關鍵字,使其在關鍵的位置停下來,以便查詢逆向突破口。

但有時候, debugger 會被網站開發者利用,使其成為阻撓我們正常除錯的攔路虎。

本節我們就來介紹一個案例,來繞過無限 Debug。

1. 案例介紹

我們先看一個案例,網址是:https://antispider8.scrape.center/,開啟這個網站,正常操作和之前的網站沒有什麼不同。但是,一旦我們開啟開發者工具,就發現它立即進入了斷點模式,如圖所示。

進入斷點模式

我們並沒有設定任何斷點,也沒有執行任何額外的指令碼,它就直接進入了斷點模式。這時候我們可以點選 Resume script execution (恢復指令碼執行)按鈕,嘗試跳過這個斷點繼續執行,如圖所示。

嘗試跳過斷點

然而不管我們按多少次,它仍然一次次地進入斷點模式,無限迴圈下去,我們可以稱這樣的情況為無限 Debugger。

這怎麼辦呢?似乎無法正常打斷點除錯了,有什麼解決辦法嗎?

辦法當然是有的,本節我們就來總結一下無限 Debugger 的應對方案。

2. 實現原理

我們首先要做的是找到無限 Debugger 的源頭。在 Sources 面板中可以看到, debugger 關鍵字出現在了一個 JavaScript 檔案裡,這時候點選左下角的格式化按鈕,如圖所示。

點選 Sources 面板中的格式化按鈕

這裡通過 setInterval 迴圈,每秒執行 1 次 debugger 語句,如圖所示。

每秒執行 1 次 debugger 語句

當然還有很多類似的實現,比如無限 for 迴圈、無限 while 迴圈、無限遞迴呼叫等,它們都是可以實現這樣的效果的,原理大同小異。

瞭解了原理,下面我們就對症下藥吧!

3. 禁用斷點

因為 debugger 其實就是對應的一個斷點,它相當於用程式碼顯式地聲明瞭一個斷點,要解除它,我們只需要禁用這個斷點就好了。

首先,我們可以禁用所有的斷點。全域性禁用開關位於 Sources 面板的右上角,叫作 Deactivate breakpoints,如圖所示。

全域性禁用開關

點選一下它,這時候就會發現所有的斷點變成了灰色,如圖所示。

禁用所有的斷點

這時候我們再重新點選一下 Resume script execution 按鈕,跳過當前斷點,頁面就不會再進入到無限 Debugger 的狀態了。

但是這種全域性禁用其實並不是一個好的方案,因為禁用之後我們也無法在其他位置增加斷點進行除錯了,所有的斷點都失效了。

這時候,我們可以選擇禁用區域性斷點。取消剛才的 Deactivate breakpoints 模式,頁面會重新進入無限 Debugger 模式,我們嘗試使用另一種方法來跳過這個無限 Debugger。

我們可能會想著去掉 Breakpoints 裡勾選的斷點,心想這樣不就禁用了嗎?大家嘗試一下取消勾選,如圖所示。

取消勾選

然而,取消之後再繼續點選 Resume 按鈕,它依然不斷地停在有 debugger 關鍵字的地方,並沒有什麼效果。

其實,Breakpoints 只代表了我們手動新增的斷點,對於 debugger 關鍵字宣告的斷點,在這裡直接取消是沒有用的。

那這種情況下還有什麼辦法嗎?

有的。我們可以先將當前 Breakpoints 裡面的斷點刪除,然後在 debugger 語句所在的行的行號上單擊滑鼠右鍵,這裡會出現一個下拉選單,如圖所示。

在行號上單擊滑鼠右鍵

這裡會有一個叫作 Never pause here 的選項,意思是從不在此處暫停,我們選擇這個選項,於是頁面變成如圖所示的樣子。

點選 Never pause here 選項後的頁面

當前斷點顯示為橙色,並且斷點前面多了一個 符號,同時 Breakpoints 也出現了剛才新增的斷點位置。這時再次點選 Resume 按鈕,就可以發現我們不會再進入無限 Debugger 模式了。

當然我們也可以選擇另外一個選項 Add conditional breakpoint,如圖所示。

Add conditional breakpoint 選項

這個模式更加高階,我們可以設定進入斷點的條件,比如在除錯過程中,期望某個變數的值大於某個具體值的時候才停下來。但在本案例中,由於這裡是無限迴圈,所以我們沒有什麼具體的變數可以作為判定依據,因此可以直接寫一個簡單的表示式來控制。

點選 Add conditional breakpoint 選項,直接填入 false 即可,如圖所示。

設定 Conditional breakpoint 為 false

設定為 false,其效果就和選擇了 Never pause here 是一樣的,重新點選 Resume 也不會進入無限 Debbugger 迴圈了。

4. 替換檔案

前文我們介紹過 Overrides 面板的用法,利用它我們可以將遠端的 JavaScript 檔案替換成本地的 JavaScript 檔案,這裡我們依然可以使用這個方法來對檔案進行替換,替換成什麼呢?

很簡單,我們只需要在新的檔案裡面把 debugger 這個關鍵字刪除。

我們將當前的 JavaScript 檔案複製到文字編輯器中,刪除或者直接註釋掉 debugger 這個關鍵字,修改如下:

setInterval((function() {
// debugger; // 可以直接刪除此行或者註釋此行
console.log("debugger")
}

開啟 Sources 面板下的 Overrides 面板,將修改後的完整 JavaScript 檔案複製進去,修改的內容如圖所示:

替換 JavaScript 檔案

替換完成之後,我們重新重新整理網頁,這時候就發現不會進入無限 Debugger 模式了。

另外我們還可以使用 Charles、Fiddler 等抓包工具進行替換,也可以使用瀏覽器外掛 ReRes 等進行替換,也可以使用 Playwright 等工具使用 Request Interception 進行替換,達成的效果是一致的,原理都是將線上載入的 JavaScript 檔案進行替換,最終消除無限 Debugger。

5. 總結

本節講解了無限 Debugger 的繞過方案,包括禁用全域性斷點、條件斷點、替換原始檔案等,從這些操作中我們也可以學習到一些 JavaScript 逆向的基本思路,建議好好掌握本內容。

本文章來源於《Python3網路爬蟲開發實戰(第二版)》

End

崔慶才的新書 《Python3網路爬蟲開發實戰(第二版)》 已經正式上市了!書中詳細介紹了零基礎用 Python 開發爬蟲的各方面知識,同時相比第一版新增了 JavaScript 逆向、Android 逆向、非同步爬蟲、深度學習、Kubernetes 相關內容,‍同時本書已經獲得 Python 之父 Guido 的推薦,目前本書正在七折促銷中!

內容介紹: 《Python3網路爬蟲開發實戰(第二版)》內容介紹

掃碼購買

好文和朋友一起看~