![]() 文 | 崔慶才 出品 | 進擊的Coder(ID:FightingCoder) 已獲得原公眾號的授權(quán)轉(zhuǎ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)站,頁面如圖所示: 接下來打開開發(fā)者工具,我們會看到類似圖 xx 所示的結(jié)果。 這里可以看到多個面板標(biāo)簽,如 Elements、Console、Sources 等,這就是開發(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 原生支持的,下面簡單列舉幾個事件。
通常,我們會給按鈕綁定一個點擊事件,它的處理邏輯一般是由 JavaScript 定義的,這樣在我們點擊按鈕的時候,對應(yīng)的 JavaScript 代碼便會執(zhí)行。比如在圖 xx 中,我們選中切換到第 2 頁的節(jié)點,右側(cè) Event Listeners 選項卡下會看到它綁定的事件。 這里有對應(yīng)事件的代碼位置,內(nèi)容為一個 JavaScript 文件名稱 所以,利用好 Event Listeners,我們可以輕松地找到各個節(jié)點綁定事件的處理方法所在的位置,幫我們在 JavaScript 逆向過程中找到一些突破口。 3. 代碼美化剛才我們已經(jīng)通過 Event Listeners 找到了對應(yīng)的事件處理方法所在的位置并成功跳轉(zhuǎn)到了代碼所在的位置。 但是,這部分代碼似乎被壓縮過了,可讀性很差,根本沒法閱讀,這時候應(yīng)該怎么辦呢? 不用擔(dān)心,Sources 面板提供了一個便捷好用的代碼美化功能。我們點擊代碼面板左下角的格式化按鈕,代碼就會變成如圖所示的樣子。 此時會新出現(xiàn)一個叫作 這個功能在調(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ā)了,如圖所示。 這時候我們可以看到頁面中顯示了一個叫作 此時代碼停在了第 4446 行,回調(diào)參數(shù) 另外我們關(guān)注到有一個方法 我們可以看到, 在 Scope 面板還有多個域,這里就不再展開介紹了。總之,通過 Scope 面板,我們可以看到當(dāng)前執(zhí)行環(huán)境下的變量的值和方法的定義,知道當(dāng)前代碼究竟執(zhí)行了怎樣的邏輯。 接下來切換到 Watch 面板,在這里可以自行添加想要查看的變量和方法,點擊右上角的 + 號按鈕,我們可以任意添加想要監(jiān)聽的對象,如圖所示。 比如這里我們比較關(guān)注 我們還可以切換到 Console 面板,輸入任意的 JavaScript 代碼,便會執(zhí)行、輸出對應(yīng)的結(jié)果,如圖所示。 如果我們想看看變量 此時我們還可以選擇單步調(diào)試,這里有 3 個重要的按鈕,如圖所示。 這 3 個按鈕都可以做單步調(diào)試,但功能不同。
用得較多的是第一個,相當(dāng)于逐行調(diào)試,比如點擊 Step Over Next Function Call 這個按鈕,就運行到了 4447 行,高亮的位置就變成了這一行,如圖所示。 5. 觀察調(diào)用棧在調(diào)試的過程中,我們可能會跳到一個新的位置,比如點擊上述 Step Over Next Function Call 幾下,可能會跳到一個叫作 那究竟是怎么跳過來的呢?我們可以觀察一下右側(cè)的 Call Stack 面板,就可以看到全部的調(diào)用過程了。比如它的上一步是 有時候調(diào)用棧是非常有用的,利用它我們可以回溯某個邏輯的執(zhí)行流程,從而快速找到突破口。 6. 恢復(fù) JavaScript 執(zhí)行在調(diào)試過程中,如果想快速跳到下一個斷點或者讓 JavaScript 代碼運行下去,可以點擊 Resume script execution 按鈕,如圖所示。 這時瀏覽器會直接執(zhí)行到下一個斷點的位置,從而避免陷入無窮無盡的調(diào)試中。 當(dāng)然,如果沒有其他斷點了,瀏覽器就會恢復(fù)正常狀態(tài)。比如這里我們就沒有再設(shè)置其他斷點了,瀏覽器直接運行并加載了下一頁的數(shù)據(jù),同時頁面恢復(fù)正常,如圖所示。 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 斷點,如圖所示。 要設(shè)置斷點,就要先觀察 Ajax 請求。和之前一樣,我們點擊翻頁按鈕 2,在 Network 面板里面觀察 Ajax 請求是怎樣的,請求的 URL 如圖所示。 可以看到 URL 里面包含 這時候我們再點擊翻頁按鈕 3,觸發(fā)第 3 頁的 Ajax 請求。會發(fā)現(xiàn)點擊之后頁面走到斷點停下來了,如圖所示。 格式化代碼看一下,發(fā)現(xiàn)它停到了 Ajax 最后發(fā)送的那個時候,即底層的 接下來切換到 可以發(fā)現(xiàn),可能使用了 因此在某些情況下,我們可以在比較容易地通過 Ajax 斷點找到分析的突破口,這是一個常見的尋找 JavaScript 逆向突破口的方法。 要取消斷點也很簡單,只需要在 XHR/fetch Breakpoints 面板取消勾選即可,如圖所示。 8. 改寫 JavaScript 文件我們知道,一個網(wǎng)頁里面的 JavaScript 是從對應(yīng)服務(wù)器上下載下來并在瀏覽器執(zhí)行的。有時候,我們可能想要在調(diào)試的過程中對 JavaScript 做一些更改,比如說有以下需求:
這時候我們可以試著在 Sources 面板中對 JavaScript 進行更改,但這種更改并不能長久生效,一旦刷新頁面,更改就全都沒有了。比如我們在 JavaScript 文件中寫入一行 JavaScript 代碼,然后保存,如圖所示。 這時候可以發(fā)現(xiàn) JavaScript 文件上出現(xiàn)了一個感嘆號標(biāo)志,提示我們做的更改是不會保存的。這時候重新刷新頁面,再看一下更改的這個文件,如圖所示。 有什么方法可以修改呢?其實有一些瀏覽器插件可以實現(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 面板上選定一個本地的文件夾,用于保存需要更改的 JavaScript 文件,我們來實際操作一下。 首先,根據(jù)上文設(shè)置 Ajax 斷點的方法,找到對應(yīng)的構(gòu)造 Ajax 請求的位置,根據(jù)一些網(wǎng)頁開發(fā)知識,我們可以大體判斷出 我們打算在 Ajax 請求成功獲得 Response 的時候,在控制臺輸出 Response 的結(jié)果,也就是通過 再切回 Overrides 面板,點擊 + 按鈕,這時候瀏覽器會提示我們選擇一個本地文件夾,用于存儲要替換的 JavaScript 文件。這里我選定了一個我任意新建的文件夾 ChromeOverrides,注意,這時候可能會遇到如圖所示的提示,如果沒有問題,直接點擊“允許”即可。 這時,在 Overrides 面板下就多了一個 ChromeOverrides 文件夾,用于存儲所有我們想要更改的 JavaScript 文件,如圖所示。 我們可以看到,現(xiàn)在所在的 JavaScript 選項卡是
接著把修改后的內(nèi)容替換到原來的 JavaScript 文件中。這里要注意,切換到 替換完畢之后保存,這時候再切換回 Overrides 面板,就可以發(fā)現(xiàn)成功生成了新的 JavaScript 文件,它用于替換原有的 JavaScript 文件,如圖所示。 好,此時我們?nèi)∠袛帱c,然后刷新頁面,就可以在控制臺看到輸出的 Reponse 結(jié)果了,如圖所示。 正如我們所料,我們成功將變量 我們還可以增加一些 JavaScript 邏輯,比如直接將變量 修改 JavaScript 文件有很多用途,此方案可以為我們進行 JavaScript 的逆向帶來極大的便利。 9. 總結(jié)本節(jié)總結(jié)了一些瀏覽器開發(fā)者工具中對 JavaScript 逆向非常有幫助的功能,熟練掌握了這些功能會對后續(xù) JavaScript 逆向分析打下堅實的基礎(chǔ),請大家好好研究。 |
|
來自: 昵稱10087950 > 《JAVA》