文章目錄
- 1. 寫在前面
- 2. 接口分析
- 3. 斷點分析
- 4. 扣代碼補環境
- 5. 數據解密
【🏠作者主頁】:吳秋霖
【💼作者介紹】:擅長爬蟲與JS加密逆向分析!Python領域優質創作者、CSDN博客專家、阿里云博客專家、華為云享專家。一路走來長期堅守并致力于Python與爬蟲領域研究與開發工作!
【🌟作者推薦】:對爬蟲領域以及JS逆向分析感興趣的朋友可以關注《爬蟲JS逆向實戰》《深耕爬蟲領域》
未來作者會持續更新所用到、學到、看到的技術知識!包括但不限于:各類驗證碼突防、爬蟲APP與JS逆向分析、RPA自動化、分布式爬蟲、Python領域等相關文章
作者聲明:文章僅供學習交流與參考!嚴禁用于任何商業與非法用途!否則由此產生的一切后果均與作者無關!如有侵權,請聯系作者本人進行刪除!
1. 寫在前面
??在去年的時候,作者有分析過關于巨量的msToken、X-Bogus、_signature三個參數的加密,本次有讀者找到作者尋求解決最新的加密算法,算法相比于之前有細微的變化,參數加密的話重新分析扣JS出來補個環境能搞定,數據解密需要分析講解一下!
2. 接口分析
打開網站,我這里的話也是按照上面讀者的闡述,主要去分析了兩個接口,這里我們直接看get_multi_keyword_hot_trend就行,如下所示:
可以看到有三個參數,我們需要重點關注分析的是X-Bogus、_signature,msToken參數的話也許是它會是一個埋點校驗的參數,可能會在大量的請求中被檢測,這里的話我們直接先固值就好或者用Cookie內的測試均可!當然動態的也可以自己使用算法去生成
msToken參數的話在簽名加密的時候需要參與加密,所以暫時是不能不要的!另外我們可以看到巨量目前的話,接口響應數據以密文的方式返回,如下所示:
所以我們需要正常的抓取數據,不僅需要解決加密參數的問題!同樣需要解密接口密文數據
3. 斷點分析
根據之前的分析,以及對某系X-bogus的早期版本分析,直接看調用棧不難看出,基本上參數的核心加密邏輯就在這個JS內,采用補環境的話就比較簡單了!如下所示:
我們先來分析X-Bogus參數,進去開始斷點跟棧分析,可以看到_0x4d83e6就是生成這個參數的方法,它接受兩個參數,_0x2a5467是msToken,_0xbe4f85則是請求參數,直接在控制臺查看一下,如下所示:
找到了X-Bogus參數生成的方法,現在我們繼續找_signature是如何生成的,跟棧來到_0x2657c0,接受三個參數!如下所示:
可以在控制打印一下參數,如下所示:
4. 扣代碼補環境
直接把webmssdk.js文件全部扣出來,拿到本地開始進行調試,如下所示:
缺什么補什么,完整的環境頭如下所示,href地址自己把接口的地址放上即可,如下所示:
window = global;
document = {}
addEventListener = function (){}
document.addEventListener = addEventListener
canvas = {}
createElement = function (){return canvas
}
document.createElement = createElement
location = {}
location.href = '' # 自行獲取
location.protocol = 'https:'
navigator = {}
navigator.userAgent = '' # 自行獲取
document.referrer = ""
setInterval = function (){}
setTimeout = function (){}
現在我們接下來需要做的就是,封裝加密方法,以便調用!將生成X-Bogus參數的_0x4d83e6方法跟生成_signature的加密方法_0x2657c0全部導出,實現如下:
// 確保get_xbogus跟get_sign以經導出加密方法!!!
function get_sign_params(msToken, api, params) {const _params = JSON.stringify(params);const xbogus = get_xbogus(`msToken=${msToken}`, _params);const url = `${api}msToken=${msToken}&X-Bogus=${xbogus}`;const _signature = get_sign({ body: params, url }, undefined, 'forreal');return {msToken,'X-Bogus': xbogus,_signature};
}
上面注釋請注意,加密函數已經導出使用!我們測試一下加密算法效果,如下所示:
我們這里直接先寫一個Demo,測試一下算法生成的參數是否可以正常拿到數據,如下所示:
很好,證明算法是沒有問題的。正常拿到了接口的密文數據,接下來我們就需要對接口返回的加密數據進行解密!
5. 數據解密
關于接口響應數據加密,作者的文章有過很多案例了!如果去分析定位!這里就不再重復的去西說,直接先Hook一下,Hook到之后可以再看跟棧去調試分析,如下所示:
Hook到解密位置,直接跟棧,斷點分析+插樁+追日志…各種分析手法結合使用,直接把氣勢先拉滿再說!找到解密方式如下所示:
如上!既然現在知道了是AES加密,那么就需要獲取到密鑰跟初始向量!密鑰如下所示:
初始向量iv,如下所示:
最后根據插樁日志跟斷點分析,來梳理一下明文數據的整個加密流程,如下所示:
1、UTF-8編碼
2、AES加密
3、Base64編碼
從而根據上面的加密流程反推解密算法,編寫解密函數!算法實現如下所示:
import base64
from Crypto.Cipher import AES
# 數據解密算法
def decrypt(ciphertext):key = "SjXbYTJb7zXoUToSicUL3A=="iv = "OekMLjghRg8vlX/PemLc+Q=="decoded_key = base64.b64decode(key)decoded_iv = base64.b64decode(iv)cipher = AES.new(decoded_key, AES.MODE_CBC, decoded_iv)decoded_ciphertext = base64.b64decode(ciphertext)plaintext = cipher.decrypt(decoded_ciphertext)padding_length = plaintext[-1]plaintext = plaintext[:-padding_length]plaintext = plaintext.decode('utf-8')return plaintext
編寫程序來調用解密算法測試一下密文數據解密后的效果,如下所示:
非常好!最終我們編寫一個完整的抓取Demo,來看看抓取效果,如下所示:
import re
import json
import execjs
import requests
from loguru import loggerheaders = {} # 自行獲取cookies = {} # 自行獲取url = "https://trendinsight.oceanengine.com/api/v2/index/get_multi_keyword_hot_trend"data = {"keyword_list": ["小米su7"],"start_date": "20240501","end_date": "20240510","app_name": "toutiao","region": []
}with open('./juliang.js', 'r') as f:js_code = f.read()ctx = execjs.compile(js_code)params_dict = ctx.call('get_param', '', url, data)
x_bogus = params_dict['X-Bogus']
_signature = params_dict['_signature']params = {"msToken": cookies['msToken'],"X-Bogus": x_bogus,"_signature":_signature
}data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data).json()result = decrypt(response['data'])logger.info(f'解密數據: {result}')