日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

JavaScript 逆向爬蟲中的瀏覽器調(diào)試常見技巧

 昵稱10087950 2022-06-16 發(fā)布于江蘇
圖片
 關(guān)注
腳本之家
,與百萬開發(fā)者在一起

圖片

文 | 崔慶才

出品 | 進擊的Coder(ID:FightingCoder)

已獲得原公眾號的授權(quán)轉(zhuǎn)載

注:本文來自《Python3網(wǎng)絡(luò)爬蟲開發(fā)實戰(zhàn)(第二版)》一書。

現(xiàn)在越來越多的網(wǎng)站也已經(jīng)應(yīng)用了這些技術(shù)對其數(shù)據(jù)接口進行了保護,在做爬蟲時如果我們遇到了這種情況,我們可能就不得不硬著頭皮來去想方設(shè)法找出其中隱含的關(guān)鍵邏輯了,這個過程我們可以稱之為 JavaScript 逆向。

既然我們要做 JavaScript 逆向,那少不了要用到瀏覽器的開發(fā)者工具,因為網(wǎng)頁是在瀏覽器中加載的,所以多數(shù)的調(diào)試過程也是在瀏覽器中完成的。

工欲善其事,必先利其器。本節(jié)我們先來基于 Chrome 瀏覽器介紹一下瀏覽器開發(fā)者工具的使用。但由于開發(fā)者工具功能十分復(fù)雜,本節(jié)主要介紹對 JavaScript 逆向有一些幫助的功能,學(xué)會了這些,我們在做 JavaScript 逆向調(diào)試的過程會更加得心應(yīng)手。

本節(jié)我們以一個示例網(wǎng)站 https://spa2./ 來做演示,用這個示例來介紹瀏覽器開發(fā)者工具各個面版的用法。

1. 面板介紹

首先我們用 Chrome 瀏覽器打開示例網(wǎng)站,頁面如圖所示:

圖片
示例網(wǎng)站頁面

接下來打開開發(fā)者工具,我們會看到類似圖 xx 所示的結(jié)果。

圖片
打開開發(fā)者工具

這里可以看到多個面板標(biāo)簽,如 Elements、Console、Sources 等,這就是開發(fā)者工具的一個個面板,功能豐富而又強大,先對面板作下簡單的介紹:

  • Elements:元素面板,用于查看或修改當(dāng)前網(wǎng)頁 HTML 節(jié)點的屬性、CSS 屬性、監(jiān)聽事件等等,HTML 和 CSS 都可以即時修改和即時顯示。
  • Console:控制臺面板,用于查看調(diào)試日志或異常信息。另外我們還可以在控制臺輸入 JavaScript 代碼,方便調(diào)試。
  • Sources:源代碼面板,用于查看頁面的 HTML 文件源代碼、JavaScript 源代碼、CSS 源代碼,還可以在此面板對 JavaScript 代碼進行調(diào)試,比如添加和修改 JavaScript 斷點,觀察 JavaScript 變量變化等。
  • Network:網(wǎng)絡(luò)面板,用于查看頁面加載過程中的各個網(wǎng)絡(luò)請求,包括請求、響應(yīng)等各個詳情。
  • Performance:性能面板,用于記錄和分析頁面在運行時的所有活動,比如 CPU 占用情況,呈現(xiàn)頁面性能分析結(jié)果,
  • Memory:內(nèi)存面板,用于記錄和分析頁面占用內(nèi)存情況,如查看內(nèi)存占用變化,查看 JavaScript 對象和 HTML 節(jié)點的內(nèi)存分配。
  • Application:應(yīng)用面板,用于記錄網(wǎng)站加載的所有資源信息,如存儲、緩存、字體、圖片等,同時也可以對一些資源進行修改和刪除。
  • Lighthouse:審核面板,用于分析網(wǎng)絡(luò)應(yīng)用和網(wǎng)頁,收集現(xiàn)代性能指標(biāo)并提供對開發(fā)人員最佳實踐的意見。

了解了這些面板之后,我們來深入了解幾個面板中對 JavaScript 調(diào)試很有幫助的功能。

2. 查看節(jié)點事件

之前我們是用 Elements 面板來審查頁面的節(jié)點信息的,我們可以查看當(dāng)前頁面的 HTML 源代碼及其在網(wǎng)頁中對應(yīng)的位置,查看某個條目的標(biāo)題對應(yīng)的頁面源代碼,如圖所示。

圖片
查看源代碼

點擊右側(cè)的 Styles 選項卡,可以看到對應(yīng)節(jié)點的 CSS 樣式,我們可以自行在這里增刪樣式,實時預(yù)覽效果,這對網(wǎng)頁開發(fā)十分有幫助。

在 Computed 選項卡中還可以看到當(dāng)前節(jié)點的盒子模型,比如外邊距、內(nèi)邊距等,還可以看到當(dāng)前節(jié)點最終計算出的 CSS 的樣式,如圖所示。

圖片
盒子模型

接下來切換到右側(cè)的 Event Listeners 選項卡,這里可以顯示各個節(jié)點當(dāng)前已經(jīng)綁定的事件,都是 JavaScript 原生支持的,下面簡單列舉幾個事件。

  • change:HTML 元素改變時會觸發(fā)的事件。
  • click:用戶點擊 HTML 元素時會觸發(fā)的事件。
  • mouseover:用戶在一個 HTML 元素上移動鼠標(biāo)會觸發(fā)的事件。
  • mouseout:用戶從一個 HTML 元素上移開鼠標(biāo)會觸發(fā)的事件。
  • keydown:用戶按下鍵盤按鍵會觸發(fā)的事件。
  • load:瀏覽器完成頁面加載時會觸發(fā)的事件。

通常,我們會給按鈕綁定一個點擊事件,它的處理邏輯一般是由 JavaScript 定義的,這樣在我們點擊按鈕的時候,對應(yīng)的 JavaScript 代碼便會執(zhí)行。比如在圖 xx 中,我們選中切換到第 2 頁的節(jié)點,右側(cè) Event Listeners 選項卡下會看到它綁定的事件。

圖片
選中切換到第 2 頁的節(jié)點

這里有對應(yīng)事件的代碼位置,內(nèi)容為一個 JavaScript 文件名稱 chunk-vendors.77daf991.js,然后緊跟一個冒號,然后再跟了一個數(shù)字 7。所以對應(yīng)的事件處理函數(shù)是定義在 chunk-vendors.77daf991.js 這個文件的第 7 行。點擊這個代碼位置,便會自動跳轉(zhuǎn) Sources 面板,打開對應(yīng)的 chunk-vendors.77daf991.js 文件并跳轉(zhuǎn)到對應(yīng)的位置,如圖所示。

圖片
跳轉(zhuǎn)到對應(yīng)的代碼位置

所以,利用好 Event Listeners,我們可以輕松地找到各個節(jié)點綁定事件的處理方法所在的位置,幫我們在 JavaScript 逆向過程中找到一些突破口。

3. 代碼美化

剛才我們已經(jīng)通過 Event Listeners 找到了對應(yīng)的事件處理方法所在的位置并成功跳轉(zhuǎn)到了代碼所在的位置。

但是,這部分代碼似乎被壓縮過了,可讀性很差,根本沒法閱讀,這時候應(yīng)該怎么辦呢?

不用擔(dān)心,Sources 面板提供了一個便捷好用的代碼美化功能。我們點擊代碼面板左下角的格式化按鈕,代碼就會變成如圖所示的樣子。

圖片
代碼格式化按鈕
圖片
格式化后的代碼

此時會新出現(xiàn)一個叫作 chunk-vendors.77daf991.js:formatted 的選項卡,文件名后面加了 formatted 標(biāo)識,代表這是被格式化的結(jié)果。我們會發(fā)現(xiàn),原來代碼在第 7 行,現(xiàn)在自動對應(yīng)到了第 4445 行,而且對應(yīng)的代碼位置會高亮顯示,代碼可讀性大大增強!

這個功能在調(diào)試過程中非常常用,用好這個功能會給我們的 JavaScript 調(diào)試過程帶來極大的便利。

4. 斷點調(diào)試

接下來介紹一個非常重要的功能——斷點調(diào)試。在調(diào)試代碼的時候,我們可以在需要的位置上打斷點,當(dāng)對應(yīng)事件觸發(fā)時,瀏覽器就會自動停在斷點的位置等待調(diào)試,此時我們可以選擇單步調(diào)試,在面板中觀察調(diào)用棧、變量值,以更好地追蹤對應(yīng)位置的執(zhí)行邏輯。

那么斷點怎么打呢?我們接著以上面的例子來說。首先單擊如圖所示的代碼行號。

圖片
單擊代碼行號

這時候行號處就出現(xiàn)了一個藍色的箭頭,這就證明斷點已經(jīng)添加好了,同時在右側(cè)的 Breakpoints 選項卡下會出現(xiàn)我們添加的斷點的列表。

由于我們知道這個斷點是用來處理翻頁按鈕的點擊事件的,所以可以在網(wǎng)頁里面點擊按鈕試一下,比如點擊第 2 頁的按鈕,這時候就會發(fā)現(xiàn)斷點被觸發(fā)了,如圖所示。

圖片
斷點被觸發(fā)

這時候我們可以看到頁面中顯示了一個叫作 Paused in debugger 的提示,這說明瀏覽器執(zhí)行到剛才我們設(shè)置斷點的位置處就不再繼續(xù)執(zhí)行了,等待我們發(fā)號施令執(zhí)行調(diào)試。

此時代碼停在了第 4446 行,回調(diào)參數(shù) e 就是對應(yīng)的點擊事件 MouseEvent 。在右側(cè)的 Scope 面板處,可以觀察到各個變量的值,比如在 Local 域下有當(dāng)前方法的局部變量,我們可以在這里看到 MouseEvent 的各個屬性,如圖所示。

圖片
查看 Local 域

另外我們關(guān)注到有一個方法 o,它在 Jr 方法下面,所以切換到 Closure(Jr) 域可以查看它的定義及其接收的參數(shù),如圖所示。

圖片
查看 Closure(Jr) 域

我們可以看到,FunctionLocation 又指向了方法 o ,點擊之后便又可以跳到指定位置,用同樣的方式進行斷點調(diào)試即可。

在 Scope 面板還有多個域,這里就不再展開介紹了。總之,通過 Scope 面板,我們可以看到當(dāng)前執(zhí)行環(huán)境下的變量的值和方法的定義,知道當(dāng)前代碼究竟執(zhí)行了怎樣的邏輯。

接下來切換到 Watch 面板,在這里可以自行添加想要查看的變量和方法,點擊右上角的 + 號按鈕,我們可以任意添加想要監(jiān)聽的對象,如圖所示。

圖片
Watch 面板

比如這里我們比較關(guān)注 o.apply 是一個怎樣的方法,于是點擊添加 o.apply,這里就會把對應(yīng)的方法定義呈現(xiàn)出來,展開之后可以再點擊 FunctionLocation 定位其源碼位置。

我們還可以切換到 Console 面板,輸入任意的 JavaScript 代碼,便會執(zhí)行、輸出對應(yīng)的結(jié)果,如圖所示。

圖片
Console 面板

如果我們想看看變量 arguments 的第一個元素是什么,那么可以直接敲入 arguments[0],便會輸出對應(yīng)的結(jié)果 MouseEvent,只要在當(dāng)前上下文能訪問到的變量都可以直接引用并輸出。

此時我們還可以選擇單步調(diào)試,這里有 3 個重要的按鈕,如圖所示。

圖片
單步調(diào)試按鈕

這 3 個按鈕都可以做單步調(diào)試,但功能不同。

  • Step Over Next Function Call:逐語句執(zhí)行
  • Step Into Next Function Call:進入方法內(nèi)部執(zhí)行
  • Step Out of Current Function:跳出當(dāng)前方法

用得較多的是第一個,相當(dāng)于逐行調(diào)試,比如點擊 Step Over Next Function Call 這個按鈕,就運行到了 4447 行,高亮的位置就變成了這一行,如圖所示。

圖片
點擊 Step Over Next Function Call 按鈕

5. 觀察調(diào)用棧

在調(diào)試的過程中,我們可能會跳到一個新的位置,比如點擊上述 Step Over Next Function Call 幾下,可能會跳到一個叫作 ct 的方法中,這時候我們也不知道發(fā)生了什么,如圖所示。

圖片
跳到 ct 方法中

那究竟是怎么跳過來的呢?我們可以觀察一下右側(cè)的 Call Stack 面板,就可以看到全部的調(diào)用過程了。比如它的上一步是 ot 方法,再上一步是 pt 方法,點擊對應(yīng)的位置也可以跳轉(zhuǎn)到對應(yīng)的代碼位置,如圖所示。

圖片
Call Stack 面板

有時候調(diào)用棧是非常有用的,利用它我們可以回溯某個邏輯的執(zhí)行流程,從而快速找到突破口。

6. 恢復(fù) JavaScript 執(zhí)行

在調(diào)試過程中,如果想快速跳到下一個斷點或者讓 JavaScript 代碼運行下去,可以點擊 Resume script execution 按鈕,如圖所示。

圖片
Resume script execution 按鈕

這時瀏覽器會直接執(zhí)行到下一個斷點的位置,從而避免陷入無窮無盡的調(diào)試中。

當(dāng)然,如果沒有其他斷點了,瀏覽器就會恢復(fù)正常狀態(tài)。比如這里我們就沒有再設(shè)置其他斷點了,瀏覽器直接運行并加載了下一頁的數(shù)據(jù),同時頁面恢復(fù)正常,如圖所示。

圖片
瀏覽器恢復(fù)正常狀態(tài)

7. Ajax 斷點

上面我們介紹了一些 DOM 節(jié)點的 Listener,通過 Listener 我們可以手動設(shè)置斷點并進行調(diào)試。但其實針對這個例子,通過翻頁的點擊事件 Listener 是不太容易找到突破口的。

接下來我們再介紹一個方法—— Ajax 斷點,它可以在發(fā)生 Ajax 請求的時候觸發(fā)斷點。對于這個例子,我們的目標(biāo)其實就是找到 Ajax 請求的那一部分邏輯,找出加密參數(shù)是怎么構(gòu)造的??梢韵氲?,通過 Ajax 斷點,使頁面在獲取數(shù)據(jù)的時候停下來,我們就可以順著找到構(gòu)造 Ajax 請求的邏輯了。

怎么設(shè)置呢?

我們把之前的斷點全部取消,切換到 Sources 面板下,然后展開 XHR/fetch Breakpoints,這里就可以設(shè)置 Ajax 斷點,如圖所示。

圖片
展開 XHR/fetch Breakpoints

要設(shè)置斷點,就要先觀察 Ajax 請求。和之前一樣,我們點擊翻頁按鈕 2,在 Network 面板里面觀察 Ajax 請求是怎樣的,請求的 URL 如圖所示。

圖片
請求的 URL

可以看到 URL 里面包含 /api/movie 這樣的內(nèi)容,所以我們可以在剛才的 XHR/fetch Breakpoints 面板中添加攔截規(guī)則。點擊 + 號,可以看到一行 Break when URL contains: 的提示,意思是當(dāng) Ajax 請求的 URL 包含填寫的內(nèi)容時,會進入斷點停止,這里可以填寫 /api/movie,如圖所示。

圖片

這時候我們再點擊翻頁按鈕 3,觸發(fā)第 3 頁的 Ajax 請求。會發(fā)現(xiàn)點擊之后頁面走到斷點停下來了,如圖所示。

圖片
斷點調(diào)試模式

格式化代碼看一下,發(fā)現(xiàn)它停到了 Ajax 最后發(fā)送的那個時候,即底層的 XMLHttpRequestsend 方法,可是似乎還是找不到 Ajax 請求是怎么構(gòu)造的。前面我們講過調(diào)用棧 Call Stack,通過調(diào)用棧是可以順著找到前序調(diào)用邏輯的,所以順著調(diào)用棧一層層找,也可以找到構(gòu)造 Ajax 請求的邏輯,最后會找到一個叫作 onFetchData 的方法,如圖所示。

圖片
找到 onFetchData 方法

接下來切換到 onFetchData 方法并將代碼格式化,可以看到如圖所示的調(diào)用方法。

圖片
調(diào)用方法

可以發(fā)現(xiàn),可能使用了 axios 庫發(fā)起了一個 Ajax 請求,還有 limitoffset、token 這 3 個參數(shù),基本就能確定了,順利找到了突破口!我們就不在此展開分析了,后文會有完整的分析實戰(zhàn)。

因此在某些情況下,我們可以在比較容易地通過 Ajax 斷點找到分析的突破口,這是一個常見的尋找 JavaScript 逆向突破口的方法。

要取消斷點也很簡單,只需要在 XHR/fetch Breakpoints 面板取消勾選即可,如圖所示。

圖片
取消斷點

8. 改寫 JavaScript 文件

我們知道,一個網(wǎng)頁里面的 JavaScript 是從對應(yīng)服務(wù)器上下載下來并在瀏覽器執(zhí)行的。有時候,我們可能想要在調(diào)試的過程中對 JavaScript 做一些更改,比如說有以下需求:

  • 發(fā)現(xiàn) JavaScript 文件中包含很多阻撓調(diào)試的代碼或者無效代碼、干擾代碼,想要將其刪除。

  • 調(diào)試到某處,想要加一行 console.log 輸出一些內(nèi)容,以便觀察某個變量或方法在頁面加載過程中的調(diào)用情況。在某些情況下,這種方法比打斷點調(diào)試更方便。

  • 調(diào)試過程遇到某個局部變量或方法,想要把它賦值給 window 對象以便全局可以訪問或調(diào)用。

  • 在調(diào)試的時候,得到的某個變量中可能包含一些關(guān)鍵的結(jié)果,想要加一些邏輯將這些結(jié)果轉(zhuǎn)發(fā)到對應(yīng)的目標(biāo)服務(wù)器。

這時候我們可以試著在 Sources 面板中對 JavaScript 進行更改,但這種更改并不能長久生效,一旦刷新頁面,更改就全都沒有了。比如我們在 JavaScript 文件中寫入一行 JavaScript 代碼,然后保存,如圖所示。

圖片
在 JavaScript 文件中寫入一行 JavaScript 代碼

這時候可以發(fā)現(xiàn) JavaScript 文件上出現(xiàn)了一個感嘆號標(biāo)志,提示我們做的更改是不會保存的。這時候重新刷新頁面,再看一下更改的這個文件,如圖所示。

圖片
刷新頁面后的 JavaScript 文件

有什么方法可以修改呢?其實有一些瀏覽器插件可以實現(xiàn),比如 ReRes。在插件中,我們可以添加自定義的 JavaScript 文件,并配置 URL 映射規(guī)則,這樣瀏覽器在加載某個在線 JavaScript 文件的時候就可以將內(nèi)容替換成自定義的 JavaScript 文件了。另外,還有一些代理服務(wù)器也可以實現(xiàn),比如 Charles、Fiddler,借助它們可以在加載 JavaScript 文件時修改對應(yīng) URL 的響應(yīng)內(nèi)容,以實現(xiàn)對 JavaScript 文件的修改。

其實瀏覽器的開發(fā)者工具已經(jīng)原生支持這個功能了,即瀏覽器的 Overrides 功能,它在 Sources 面板左側(cè),如圖所示。

圖片
Overrides 功能

我們可以在 Overrides 面板上選定一個本地的文件夾,用于保存需要更改的 JavaScript 文件,我們來實際操作一下。

首先,根據(jù)上文設(shè)置 Ajax 斷點的方法,找到對應(yīng)的構(gòu)造 Ajax 請求的位置,根據(jù)一些網(wǎng)頁開發(fā)知識,我們可以大體判斷出 then 后面的回調(diào)方法接收的參數(shù) a 中就包含了 Ajax 請求的結(jié)果,如圖所示。

圖片

我們打算在 Ajax 請求成功獲得 Response 的時候,在控制臺輸出 Response 的結(jié)果,也就是通過 console.log 輸出變量 a

再切回 Overrides 面板,點擊 + 按鈕,這時候瀏覽器會提示我們選擇一個本地文件夾,用于存儲要替換的 JavaScript 文件。這里我選定了一個我任意新建的文件夾 ChromeOverrides,注意,這時候可能會遇到如圖所示的提示,如果沒有問題,直接點擊“允許”即可。

圖片
彈出提示

這時,在 Overrides 面板下就多了一個 ChromeOverrides 文件夾,用于存儲所有我們想要更改的 JavaScript 文件,如圖所示。

圖片
Overrides 面板下出現(xiàn) ChromeOverrides 文件夾

我們可以看到,現(xiàn)在所在的 JavaScript 選項卡是 chunk-19c920f8.012555a2.js:formatted,代碼已經(jīng)被格式化了。因為格式化后的代碼是無法直接在瀏覽器中修改的,所以為了方便,我們可以將格式化后的文件復(fù)制到文本編輯器中,然后添加一行代碼,修改如下:

...
}).then((function(a) {
  console.log('response', a) // 添加一行代碼
  var e = a.data
   , s = e.results
   , n = e.count;
  t.loading = !1,
...

接著把修改后的內(nèi)容替換到原來的 JavaScript 文件中。這里要注意,切換到 chunk-19c920f8.012555a2.js 文件才能修改,直接替換 JavaScript 文件的所有內(nèi)容即可,如圖所示。

圖片
替換 JavaScript 文件的所有內(nèi)容

替換完畢之后保存,這時候再切換回 Overrides 面板,就可以發(fā)現(xiàn)成功生成了新的 JavaScript 文件,它用于替換原有的 JavaScript 文件,如圖所示。

圖片
生成了新的 JavaScript 文件

好,此時我們?nèi)∠袛帱c,然后刷新頁面,就可以在控制臺看到輸出的 Reponse 結(jié)果了,如圖所示。

圖片
Reponse 結(jié)果

正如我們所料,我們成功將變量 a 輸出,其中的 data 字段就是 Ajax 的 Response 結(jié)果,證明改寫 JavaScript 成功!而且刷新頁面也不會丟失了。

我們還可以增加一些 JavaScript 邏輯,比如直接將變量 a 的結(jié)果通過 API 發(fā)送到遠程服務(wù)器,并通過服務(wù)器將數(shù)據(jù)保存下來,也就完成了直接攔截 Ajax 請求并保存數(shù)據(jù)的過程了。

修改 JavaScript 文件有很多用途,此方案可以為我們進行 JavaScript 的逆向帶來極大的便利。

9. 總結(jié)

本節(jié)總結(jié)了一些瀏覽器開發(fā)者工具中對 JavaScript 逆向非常有幫助的功能,熟練掌握了這些功能會對后續(xù) JavaScript 逆向分析打下堅實的基礎(chǔ),請大家好好研究。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多