1. 程式人生 > 實用技巧 >JavaScript逆向教程之破解某麥引數加密的思路

JavaScript逆向教程之破解某麥引數加密的思路

原 文:http://www.threetails.xyz/2019/05/19/初探js逆向(二)

· 正 · 文 · 來 · 啦 ·

前言

如果你是沒有任何 js 逆向經驗的爬蟲萌新,且沒看過上篇的《JavaScript逆向教程,不來了解一下麼?》,建議先移步去看,因為本篇所使用的案例相對上篇,難度會更大一些。

在上一篇中,我們學習了一個入門案例的逆向流程。然而,加密的方式有很多,不可能以一概全。在進入本篇正題前,我們先回憶一下上篇的逆向思路:

不妨思考一下,引數雖做了加密,但網頁畢竟要正常顯示內容,所以在網頁渲染的過程中,一定有個地方對這個引數做了解密,然後將資料寫入html。

也就是說,我們需要在網頁渲染的過程裡,一步步觀察,看看到底是哪個位置對這個引數做了解密。

其實,這個思路有個前提:加密引數必須是請求返回的結果引數。如果網站在請求發起時就對請求引數做了加密,這個思路就不管用了。

另外,在上篇中,因為案例比較簡單,在找到解密函式之後工作就完成了 90%,所以摳程式碼的部分我們一筆帶過。而本篇的案例,即便找到了加密位置,可能也只完成了一半工作。

所以本篇將以七麥資料這個網站為例,介紹‘當請求引數被加密時的逆向思路’以及‘摳程式碼’的正確姿勢。

網站分析

訪問 https://www.qimai.cn/rank/marketRank/market/3/category/-2/date/2019-05-18 這個地址,可以看到:

紅框中的App榜單列表即為我們的目標資料。來看看它發起了哪些請求:

marketRank 這個請求的響應內容裡能夠找到我們的目標資料,而且是清晰的 json 結構。但不要高興得太早,我們再看一下它的請求引數:

market(3)category(-2)date 分別表示應用商店(應用寶)、類別(全部遊戲)和日期,想構造它們都很簡單,為了後文描述方便,我們暫且稱之為‘簡單三參’。

需要重點關注的是這個 analysis,它是一個被加密的必選引數,請求時必須攜帶,否則無法正常返回資料。這時候你可能會想:“那我直接把它拷貝下來,模擬請求時再帶上不就行了?”,然而,只要你稍微分析下就會發現,這個引數並不是固定的,它會隨著簡單三參的變化而改變。且這類榜單資料通常具有時效性,如果你想進行批量

持久地爬取有效資料,這種‘提前收集 analysis ’的方式是不現實的。

說了這麼多,好像有些偏離主題了,我們的目的不是爬取網站,而是學習 js 逆向。

下面進入正題。

逆向思路

我們先用上篇中提到的方式,在xhr請求裡打上斷點,重新整理一下網頁。

程式碼執行到了 h.send(f),等等,好像哪裡不對。send 不就是把請求傳送出去嗎?那是不是意味著請求引數在這步之前就已經生成完畢?觀察一下上面幾行程式碼,果然如此:

1558181366544

t 物件的 url 屬性中可以看到,analysis 已經生成好了。那麼我們再往下執行也沒意義了,因為這個請求已經被髮送到了服務端,客戶端沒必要再對它的引數進行解密。況且我們的目的是研究如何生成 analysis,而不是如何解密。

那怎樣才能找到生成 analysis 的位置呢?我們可以先把它的值記錄下來,

fGR5SX10dQ0oY3lVeGIkBH1HDQ1wExcWVlYPG1sAQltVRGJRXlMkFAxXBANUAQUHBQQFcBtV

然後把斷點打在一個比較早的地方(analysis 生成之前),一步步往下執行,這個值首次出現的位置,就是它生成的位置。

想把斷點打在 analysis 生成之前,可以在 Network 選項卡下,該請求的 Initiator 列裡看到它的呼叫棧,呼叫順序由上而下:

1558182881027

在前幾條裡隨便選一個,點進去打上斷點,這裡我看get比較順眼,就選了這條,並在預設位置打上斷點。打上斷點後別急著重新整理網頁,這裡有個坑需要先避一下。因為除了marketRank之外,marketList這個請求也有一個 analysis 引數,它請求的是應用商店列表(百度、應用寶、360…)。為了避免干擾,我們不要重新整理網頁,而是切換類別:

通過這種方式來觸發除錯介面,就不會再去請求應用商店列表了。切換類別後即可觸發彈出除錯介面:

1558183179819

可以發現,簡單三參都已經出現了,但還沒發現 analysis,它應該還沒生成,讓我們繼續往下執行。注意,執行過程中時刻關注是否出現類似(切換了類別,analysis肯定會變化,所以是類似)我們之前記錄下來的那個值。

此處省略一萬步除錯……,只要你耐心足夠,就能找到下圖中的程式碼:

1558184945255

可以看到,r 的值與我們之前記錄的值很類似,為了進一步確定,可以在除錯執行完成後看下請求中的 analysis 值是否與這個 r 的值一致。

答案是一致的。也就是說,接下來只要把 r 的生成程式碼全部摳下來,我們就能生成 analysis 了。感覺也沒那麼難對吧?其實這個網站,摳程式碼才是重頭戲。

摳程式碼

開頭中提到,本案例即便找到了加密位置,也只完成了一半工作。因為加密函式中做了大量的程式碼混淆和迷惑眼球的函式呼叫,想把它完整摳下來也不是件容易的事。如果你沒有強大的心臟和足夠的耐心,請止步於此;但如果你就喜歡折騰,請接著往下看。

鑑於本文的目的主要在於介紹‘請求引數被加密時的逆向思路’,所以不會對‘摳程式碼’的部分做詳細講解,也不會提供完整程式碼,但會稍微做一些提示,希望能對你有所幫助。以下提示內容只有真正去嘗試摳程式碼的人才能看懂了。

  1. b 寫死。

  2. 摳出 e 的生成函式,生成 e

  • 時間戳與寫死的-44

  1. 摳出 m 的生成函式,通過簡單三參+URL 字尾+e 生成 m

  • 簡單三參 sort 與 join

  • 忽略迷惑程式碼 ano[Ao]…

  • 進入 e 內部打斷點

  • 只關注被呼叫並執行的程式碼

  • new一個Unit8Array

  • 找到寫入Unit8Array的程式碼

  • 轉base64

  • 封裝f[La],便於步驟4呼叫

  1. 摳出 r 的生成函式,通過 mb 生成 r

  • 搞定步驟3之後心態千萬不要崩,因為勝利就在眼前

  • 幾個寫死的變數

  • String["fromCharCode"]

貼張逆向成功的截圖:

總結

當請求的引數被加密時,將斷點打在加密引數生成之前,在它的值首次出現的位置找到它的加密函式。

摳程式碼時,如果程式碼做了大量混淆。需要辨別哪些程式碼是迷惑你的,哪些程式碼是真正起作用的,哪些程式碼是不需要摳的,哪些程式碼是可以自己用其他方式替代的。

大週末的在家研究js破解,辛苦作者了。