JS逆向:破解某站 password 參數加密邏輯 1. 定位代碼 2. 分析調試 3. js代碼實現

目標站點:aHR0cDovL2VpcC5jaGFuZmluZS5jb20vbG9naW4uanNw

說明: 該站點較簡單,可以作爲小白練手使用,方便理解 js 逆向常規步驟。

1. 定位代碼

  • 打開調試面板,輸入手機號、密碼,點擊登錄,檢查 Network,分析後發現箭頭指向的請求,分析發現參數 j_password 已經被加密;
  • 全局搜索 j_password,下斷點,重新輸入賬號密碼,網頁在下圖位置被斷住,分析發現 desEncrypt 函數返回的結果就是被解密後的數據;

2. 分析調試

  • 回溯,進入 function desEncrypt(value, xForm, type) 中,分析發現 _0(xForm) 結果爲 false,在 else 代碼 keyObj = SECURITYKEY.get(); 處下斷,如下圖;
  • 回溯分析 SECURITYKEY.get() 函數,在代碼 str = SECURITYKEY._2(); 處下斷,回溯分析 SECURITYKEY._2() 函數,發現該函數是通過 ajax 發送請求得到返回結果的,請求的 url 中包含 js/session.jsp?_=,並且還跟了一個時間戳後綴,通過搜索過濾請求,找到了目標 url: http://eip.chanfine.com/resource/js/session.jsp?_=1637761979345&s_ajax=true,該 url 尾部也跟了一個時間戳;
  • 訪問上面拿到的 url,得到如下返回值,正是我們想要的。
function getSessionId(){
    return "3B9B93AF595C0F909356C09468D9F041";
}
  • 回退,繼續單步調試,發現 encodeType == null || encodeType == 'aes' 結果爲 true,此處 else 條件分支可以忽略。單步調試後發現,前述的返回值被分割成多個部分並賦值給了一個對象 key,最後返回了一個對象;
  • 再次回退,分析 CryptoJS.AES.encrypt(value, CryptoJS.enc.Utf8.parse(keyObj.key)

分析發現
-- keyObj.key 就是前面得到的 key 對象的 key 屬性值,
-- CryptoJS.enc.Utf8.parse() 函數對應的函數在122行:

parse: function(a) {
            return b.parse(unescape(encodeURIComponent(a)))
        }

-- 分析上面的代碼,encodeURIComponent 是內生的自帶函數,unescape() 也是內生的自帶函數,而且兩個函數都爲對傳入的參數 a 做任何修改。需要繼續回溯分析的 b.parse() 函數,對應函數代碼爲:

parse: function(a) {
            for (var c = a.length, e = [], j = 0; j < c; j++)
                e[j >>> 2] |= (a.charCodeAt(j) & 255) << 24 - 8 * (j % 4);
            return new r.init(e,c)
        }

-- 分析上面的代碼,發現其執行過程包括一個 for 循環,單步調試發現並不需要進一步回溯,需要回溯的是return 的 new r.init(e,c),繼續回溯得到如下代碼:

init: function(a, c) {
            a = this.words = a || [];
            this.sigBytes = c != p ? c : 4 * a.length
        },
  • 到這一步,其實已經沒有必要繼續在扣代碼了,結合前面的上下文,可以知道整個js代碼其實可以全部扣下來,直接進行調用的,因爲 value = CryptoJS.AES.encrypt(value, CryptoJS.enc.Utf8.parse(keyObj.key), {iv:CryptoJS.enc.Utf8.parse(keyObj.iv)}).toString() 這段加密代碼,全部是對 CryptoJS 的調用。
  • 打開 console,輸出前面分析的結果;


  • 如上圖,得到加密後的內容,至此調試分析結束。

3. js代碼實現

  • 通過上面的分析,知道核心加密步驟分爲兩步:

第一步,是通過 SECURITYKEY.get() 生成一個對象,在此過程中還需要 ajax 發送一個帶時間戳的請求;
第二步,是通過 CryptoJS 中的 AESenc 進行加密處理;

  • js 代碼:
    略。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章