列表頁鏈接:https://www.qimao.com/shuku/a-a-a-a-a-a-a-click-1/
七貓中文網的反爬措施主要是cookie中的 acw_sc__v2參數, 如何確認是這個參數呢,首先清空瀏覽器中快取的關於七貓cookie資訊,重新請求
我們可以看到cookie中的資訊有這幾個, 我們來做個具體分析:
1、Hm_lpvt_*** 和 Hm_lvt_*** 這兩個是百度聯盟或者其他站做統計用的,我們不需要管
2、頁面的響應頭 set-cookie中有acw_tc 和 aliyungf_tc 這是伺服器端給我們返回來,不需要管
3、還剩下csrf-frontend、acw_sc__v2 和 HMACCOUNT_BFESS, 我們可以模擬請求測試,經測試發現只有acw_sc_v2是反爬用的
當然這裏還有個問題, 就是七貓在偵錯的時候會有無限debugger,我們需要跳過dehugger
在第三行前右鍵點選Add Conditional breakpoint 輸入break 回車繼續向下偵錯就可以了
跳過debugger後 當前鏈接返回的是一個包含js的html頁面, 可以直接的看到這裏向cookie中寫入了acw_sc__v2這個參數,然後reload()重新載入, 就可以進入正常的html頁面了
下面 下麪我們來逆向這個acw_sc__v2是如何生成的
可以看到的是reload呼叫的setCookie寫入的, 我們找下哪裏呼叫的reload直接進行搜尋,發現沒有搜尋到,我們可以看到好多都被編碼了,先解碼在搜尋,直接在網上找個js線上解碼的工具, 再次進行搜尋可以看到這裏呼叫reload(arg2)
通過Console對程式碼進行簡單還原_0x55f3(‘0x19’, ‘Pg54’)像這總就是混淆後的變數
var _0x23a392 = arg1["unsbox"]();
arg2 = _0x23a392["hexXor"](_0x5e8b26);
setTimeout(reload(arg2), 2);
// 經過多次偵錯發現 _0x23a392["hexXor"](_0x5e8b26);中_0x5e8b26是固定的爲3000176000856006061501533003690027800375
首先看第一行 var _0x23a392 = arg1"unsbox";
arg1在程式碼的第一行是寫固定的 第一次請求用正則匹配出來
var arg1 = 'F70819CD0285BF6E118357F3402F3F75C6F35182';
接下來我們需要找到unsbox函數, 通過設定斷點偵錯, 首先進入的這個韓素
我們將js進行還原, 這樣我們就能看懂了
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 = 0; _0x20a7bf < this['length']; _0x20a7bf++) {
var _0x385ee3 = this[_0x20a7bf];
for (var _0x217721 = 0; _0x217721 < _0x4b082b['length']; _0x217721++) {
if (_0x4b082b[_0x217721] == _0x20a7bf + 1) {
_0x4da0dc[_0x217721] = _0x385ee3;
}
}
}
_0x12605e = _0x4da0dc['join']('');
return _0x12605e;
}
;
接下來使用python 進行重寫
import requests
import re
def get_unsbox(arg1):
_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]
_0x4da0dc = []
_0x12605e = ''
for i in _0x4b082b:
_0x4da0dc.append(arg1[i-1])
_0x12605e = "".join(_0x4da0dc)
return _0x12605e
# arg1 是第一次請求返回js中匹配出來的
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"}
r = requests.get(url, headers=headers)
arg1 = re.findall("arg1=\'(.*?)\'", r.text)[0]
get_unsbox()
接下來看第二行 arg2 = _0x23a392[「hexXor」](_0x5e8b26); 繼續向下偵錯 進入了下面 下麪的js
一樣先進行還原, 快點拿到hexXor就知道我們找對了
String["prototype"]["hexXor"] = function(_0x4e08d8) {
var _0x5a5d3b = '';
for (var _0xe89588 = 0; _0xe89588 < this["length"] && _0xe89588 < _0x4e08d8["length"]; _0xe89588 += 2) {
var _0x401af1 = parseInt(this["slice"](_0xe89588, _0xe89588 + 2), 16);
var _0x105f59 = parseInt(_0x4e08d8["slice"](_0xe89588, _0xe89588 + 2), 16);
var _0x189e2c = (_0x401af1 ^ _0x105f59)["toString"](16);
if (_0x189e2c["length"] == 1) {
_0x189e2c = '0' + _0x189e2c;
}
_0x5a5d3b += _0x189e2c;
}
return _0x5a5d3b;
}
使用python進行重寫
def get_hexxor(s1, _0x4e08d8):
_0x5a5d3b = ''
for i in range(len(s1)):
if i % 2 != 0: continue
_0x401af1 = int(s1[i: i+2], 16)
_0x105f59 = int(_0x4e08d8[i: i+2], 16)
_0x189e2c_10 = (_0x401af1 ^ _0x105f59)
_0x189e2c = hex(_0x189e2c_10)[2:]
if len(_0x189e2c) == 1:
_0x189e2c = '0' + _0x189e2c
_0x5a5d3b += _0x189e2c
return _0x5a5d3b
# s1 爲 第一步get_unsbox()返回的值
# _0x4e08d8 爲固定的3000176000856006061501533003690027800375
# 該函數的返回值就是我們想要的arg2
第三部就是reload(arg2)將該參數寫入cookie 重新請求
下面 下麪是全部程式碼
import requests
import re
url = "https://www.qimao.com/shuku/a-a-a-a-a-a-a-click-1/"
def get_hexxor(s1, _0x4e08d8):
_0x5a5d3b = ''
for i in range(len(s1)):
if i % 2 != 0: continue
_0x401af1 = int(s1[i: i+2], 16)
_0x105f59 = int(_0x4e08d8[i: i+2], 16)
_0x189e2c_10 = (_0x401af1 ^ _0x105f59)
_0x189e2c = hex(_0x189e2c_10)[2:]
if len(_0x189e2c) == 1:
_0x189e2c = '0' + _0x189e2c
_0x5a5d3b += _0x189e2c
return _0x5a5d3b
def get_unsbox(arg1):
_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]
_0x4da0dc = []
_0x12605e = ''
for i in _0x4b082b:
_0x4da0dc.append(arg1[i-1])
_0x12605e = "".join(_0x4da0dc)
return _0x12605e
# 第一次請求獲取js程式碼
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"}
r = requests.get(url, headers=headers)
# 重js中匹配出 arg1
arg1 = re.findall("arg1=\'(.*?)\'", r.text)[0]
# 參數生成
s1 = get_unsbox(arg1)
_0x4e08d8 = "3000176000856006061501533003690027800375"
_0x12605e = get_hexxor(s1, _0x4e08d8)
print(s1, _0x12605e)
# 二次請求攜帶cookie 獲取html檔案
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36",
"cookie": "acw_sc__v2=%s" % _0x12605e}
r = requests.get(url, headers=headers, proxies=proxy)
print(r.text)
結果: