關注微信公眾號:K哥爬蟲,持續分享爬蟲進階、JS/安卓逆向等技術乾貨!
宣告
本文章中所有內容僅供學習交流,抓包內容、敏感網址、資料介面均已做脫敏處理,嚴禁用於商業用途和非法用途,否則由此產生的一切後果均與作者無關,若有侵權,請聯絡我立即刪除!
逆向目標
- 目標:X 球投資者社群 cookie 引數
acw_sc__v2
加密分析 - 主頁:
aHR0cHM6Ly94dWVxaXUuY29tL3RvZGF5
- 逆向引數:Cookie:
acw_tc=27608267164066250867189...
抓包分析
我們的爬蟲目標是:精華 —> 今日話題 —> X球熱帖,熱帖是 Ajax 載入的,很容易找到資料介面,介面沒有其他的加密引數,主要是 cookie 裡有一些值,沒有 cookie 是無法訪問的,其中,cookie 裡又有一個 acw_sc__v2
的值,是通過 JS 生成的,其他值都是首次訪問首頁得到的,抓包如下:
加密查詢
我們清除一下 cookie,開啟 F12 開發者工具,重新整理頁面,發現會進入反除錯,出現了無限 debugger,往上跟呼叫棧,可以看到這個方法裡有一大串混淆後的程式碼,拼接起來其實就是 debugger,如下圖所示:
過掉 debugger 也很簡單,需要注意的是這個站比較刁鑽,第一次訪問首頁直接是混淆的 JS 程式碼,後面才會跳轉到正常的 HTML 頁面,如果你想本地替換 JS 的話,debugger 倒是過掉了,不過後續就有可能無法除錯了,感興趣的朋友可以自己試試,這裡K哥就直接右鍵 Never pause here 永不在此處斷下了:
我們觀察這個混淆程式碼,直接搜尋 acw_sc__v2
,可以看到最後面有設定 cookie 的操作,其中 x 就是 acw_sc__v2
的值:
引數逆向
我們往上跟呼叫棧,看看 x 是怎麼得來的,這裡 setTimeout 時間一到就會執行 '\x72\x65\x6c\x6f\x61\x64\x28\x61\x72\x67\x32\x29'
,控制檯輸出一下會發現就是 reload 方法,傳入的引數是 arg2,arg2 的值就是 acw_sc__v2
的值,如下圖所示:
arg1 在頭部定義了,需要注意的是,每次重新整理,這個 arg1 會變,所以我們在後面取值時要動態獲取,我們把關鍵程式碼單獨拿出來分析一下:
var arg1 = '6A6BE0CAF2D2305297951C9A2ADBC2E8D21D48FD';
var _0x5e8b26 = _0x55f3('0x3', '\x6a\x53\x31\x59');
var _0x23a392 = arg1[_0x55f3('0x19', '\x50\x67\x35\x34')]();
arg2 = _0x23a392[_0x55f3('0x1b', '\x7a\x35\x4f\x26')](_0x5e8b26);
可以看到主要就是這個 _0x55f3()
方法,如果你直接把這個方法扣下來的話,本地執行會直接進入死迴圈,多除錯幾遍就會發現 _0x5e8b26
呼叫函式傳參每次都是一樣的,每次的結果也是一樣的,所以可以直接寫成定值,arg2 的 _0x23a392[_0x55f3('0x1b', '\x7a\x35\x4f\x26')]
其實就是用了一個匿名函式,如下圖所示:
我們直接跟進這個匿名函式,可以看到裡面同樣呼叫了很多 _0x55f3()
方法,我們直接在控制檯輸出一下,然後把結果直接拿到本地即可:
所有結果替換掉後,會發現還會依賴另一個匿名函式,最後將這兩個匿名函式全部扣下來即可:
當然如果遇到呼叫非常多 _0x55f3()
方法的情況,那就不可能挨個替換了,就需要進一步分析該函式裡面的邏輯,在本地單步除錯,看是由於什麼原因進入了死迴圈,裡面非常多的 if-else 語句,肯定是缺少某個環境導致進入 else 語句,從而導致死迴圈了,直接刪除 else 語句、補環境走 if 語句等做法都是可以的。
完整程式碼
GitHub 關注 K 哥爬蟲,持續分享爬蟲相關程式碼!歡迎 star !https://github.com/kgepachong/
以下只演示部分關鍵程式碼,不能直接執行! 完整程式碼倉庫地址:https://github.com/kgepachong...
JavaScript 加密程式碼
/* ==================================
# @Time : 2021-12-29
# @Author : 微信公眾號:K哥爬蟲
# @FileName: get_acw_sc_v2.js
# @Software: PyCharm
# ================================== */
var _0x5e8b26 = '3000176000856006061501533003690027800375'
var getAcwScV2 = function (arg1) {
String['prototype']['hexXor'] = function (_0x4e08d8) {
var _0x5a5d3b = '';
for (var _0xe89588 = 0x0; _0xe89588 < this['length'] && _0xe89588 < _0x4e08d8['length']; _0xe89588 += 0x2) {
var _0x401af1 = parseInt(this['slice'](_0xe89588, _0xe89588 + 0x2), 0x10);
var _0x105f59 = parseInt(_0x4e08d8['slice'](_0xe89588, _0xe89588 + 0x2), 0x10);
var _0x189e2c = (_0x401af1 ^ _0x105f59)['toString'](0x10);
if (_0x189e2c['length'] == 0x1) {
_0x189e2c = '0' + _0x189e2c;
}
_0x5a5d3b += _0x189e2c;
}
return _0x5a5d3b;
};
String['prototype']['unsbox'] = function () {
var _0x4b082b = [0xf, 0x23, 0x1d, 0x18, 0x21, 0x10, 0x1, 0x26, 0xa, 0x9, 0x13, 0x1f, 0x28, 0x1b, 0x16, 0x17, 0x19, 0xd, 0x6, 0xb, 0x27, 0x12, 0x14, 0x8, 0xe, 0x15, 0x20, 0x1a, 0x2, 0x1e, 0x7, 0x4, 0x11, 0x5, 0x3, 0x1c, 0x22, 0x25, 0xc, 0x24];
var _0x4da0dc = [];
var _0x12605e = '';
for (var _0x20a7bf = 0x0; _0x20a7bf < this['length']; _0x20a7bf++) {
var _0x385ee3 = this[_0x20a7bf];
for (var _0x217721 = 0x0; _0x217721 < _0x4b082b['length']; _0x217721++) {
if (_0x4b082b[_0x217721] == _0x20a7bf + 0x1) {
_0x4da0dc[_0x217721] = _0x385ee3;
}
}
}
_0x12605e = _0x4da0dc['join']('');
return _0x12605e;
};
var _0x23a392 = arg1['unsbox']();
arg2 = _0x23a392['hexXor'](_0x5e8b26);
return arg2
};
// 測試輸出
// var arg1 = '2410463826D86A52A5BB43A13A80BAE6C4122A73';
// console.log(getAcwScV2(arg1))
Python 測試程式碼
# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2021-12-29
# @Author : 微信公眾號:K哥爬蟲
# @FileName: main.py
# @Software: PyCharm
# ==================================
import re
import execjs
import requests
index_url = "脫敏處理,完整程式碼關注 GitHub:https://github.com/kgepachong/crawler"
news_test_url = "脫敏處理,完整程式碼關注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"Host": "脫敏處理,完整程式碼關注 GitHub:https://github.com/kgepachong/crawler",
"Referer": "脫敏處理,完整程式碼關注 GitHub:https://github.com/kgepachong/crawler",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36",
}
def get_complete_cookie():
complete_cookie = {}
# 第一次不帶引數訪問首頁,獲取 acw_tc 和 acw_sc__v2
response = requests.get(url=index_url, headers=headers)
complete_cookie.update(response.cookies.get_dict())
arg1 = re.findall("arg1='(.*?)'", response.text)[0]
with open('get_acw_sc_v2.js', 'r', encoding='utf-8') as f:
acw_sc_v2_js = f.read()
acw_sc__v2 = execjs.compile(acw_sc_v2_js).call('getAcwScV2', arg1)
complete_cookie.update({"acw_sc__v2": acw_sc__v2})
# 第二次訪問首頁,獲取其他 cookies
response2 = requests.get(url=index_url, headers=headers, cookies=complete_cookie)
complete_cookie.update(response2.cookies.get_dict())
return complete_cookie
def news_test(cookies):
response = requests.get(url=news_test_url, headers=headers, cookies=cookies)
print(response.json())
if __name__ == '__main__':
complete_cookie = get_complete_cookie()
news_test(complete_cookie)