天天看點

【JS 逆向百例】某市場監管平台企業資料

【JS 逆向百例】某市場監管平台企業資料

聲明

本文章中所有内容僅供學習交流,抓包内容、敏感網址、資料接口均已做脫敏處理,嚴禁用于商業用途和非法用途,否則由此産生的一切後果均與作者無關,若有侵權,請聯系我立即删除!

逆向目标

  • 目标:某建設部&某市場監管公共服務平台的企業資料
  • 首頁:aHR0cDovL2p6c2MubW9odXJkLmdvdi5jbi9kYXRhL2NvbXBhbnk=
  • 接口:aHR0cDovL2p6c2MubW9odXJkLmdvdi5jbi9hcGkvd2ViQXBpL2RhdGFzZXJ2aWNlL3F1ZXJ5L2NvbXAvbGlzdD9wZz0lcyZwZ3N6PTE1JnRvdGFsPTQ1MA==
  • 逆向參數:請求傳回的加密資料

逆向過程

本次的逆向目标是某市場監管平台的企業資料,來到某市場監管公共服務平台首頁,依次點選資料服務 —> 企業資料,嘗試抓包一下所有企業的資料,可以看到傳回的資料是經過加密的:

【JS 逆向百例】某市場監管平台企業資料

資料看不出來是什麼加密方式,但是加密分析得多了,就知道一般都是經過

CryptoJS

加密子產品加密得到的,那麼我們可以嘗試直接搜尋

CryptoJS

decrypt

等關鍵字,或者搜尋加密算法中經常用到的偏移量

iv

、模式

mode

、填充方式

padding

等,還有一般的 JSON 資料可以搜尋

JSON.parse

等,這裡直接搜尋

JSON.parse

,在 app.a9f6bb6d.js 檔案裡定位到可疑代碼,埋下斷點進行調試:

【JS 逆向百例】某市場監管平台企業資料

可以看到 e 就是解密後的資料,觀察語句

var e = JSON.parse(h(t.data));

,直接跟進 h 函數,可以看到很明顯的 AES 加密:

【JS 逆向百例】某市場監管平台企業資料
function h(t) {
    var e = d.a.enc.Hex.parse(t)
    , n = d.a.enc.Base64.stringify(e)
    , a = d.a.AES.decrypt(n, f, {
        iv: m,
        mode: d.a.mode.CBC,
        padding: d.a.pad.Pkcs7
    })
    , r = a.toString(d.a.enc.Utf8);
    return r.toString()
}           

加密模式為 CBC,填充方式為 Pkcs7,而缺少的偏移量 m、f 的值,在上面也可以找到:

f = d.a.enc.Utf8.parse("jo8j9wGw%6HbxfFn")
m = d.a.enc.Utf8.parse("0123456789ABCDEF")           

在 Python 當中,直接引入 CryptoJS,重寫這個函數即可。

完整代碼

GitHub 關注 K 哥爬蟲:

https://github.com/kuaidaili

,持續分享爬蟲相關代碼!歡迎 star !

以下隻示範部分關鍵代碼,完整代碼倉庫位址:

https://github.com/kuaidaili/crawler/

參數 JS 加密關鍵代碼

// 引用 crypto-js 加密子產品
var CryptoJS = require('crypto-js')

function getDecryptedData(t) {
    var m = CryptoJS.enc.Utf8.parse("0123456789ABCDEF"),
        f = CryptoJS.enc.Utf8.parse("jo8j9wGw%6HbxfFn"),
        e = CryptoJS.enc.Hex.parse(t),
        n = CryptoJS.enc.Base64.stringify(e),
        a = CryptoJS.AES.decrypt(n, f, {
            iv: m,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
    }),
        r = a.toString(CryptoJS.enc.Utf8);
    return r.toString()
}

// 測試樣例
// var t = '95780ba094xxxxxxxxxx'
// console.log(getDecryptedData(t))           

Python 關鍵代碼

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import json

import execjs
import requests


data_url = '脫敏處理,完整代碼關注 GitHub:https://github.com/kuaidaili/crawler/'


def get_encrypted_data(page):
    headers = {
        'Host': '脫敏處理,完整代碼關注 GitHub:https://github.com/kuaidaili/crawler/',
        'Referer': '脫敏處理,完整代碼關注 GitHub:https://github.com/kuaidaili/crawler/',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }
    encrypted_data = requests.get(url=data_url % page, headers=headers).text
    return encrypted_data


def get_decrypted_data(encrypted_data):
    with open('jzsc_mohurd_decrypt.js', 'r', encoding='utf-8') as f:
        jzsc_mohurd_js = f.read()
    decrypted_data = execjs.compile(jzsc_mohurd_js).call('getDecryptedData', encrypted_data)
    return json.loads(decrypted_data)


def main():
    # 30頁資料
    for page in range(30):
        encrypted_data = get_encrypted_data(page)
        decrypted_data = get_decrypted_data(encrypted_data)
        print(decrypted_data)


if __name__ == '__main__':
    main()