找工程承包app排名優(yōu)化seo
一、數(shù)據(jù)接口分析
主頁地址:某網(wǎng)站
1、抓包
通過抓包可以發(fā)現(xiàn)數(shù)據(jù)接口是page
2、判斷是否有加密參數(shù)
- 請求參數(shù)是否加密?
通過查看“載荷”模塊可以發(fā)現(xiàn),請求參數(shù)是一整個(gè)密文
- 請求頭是否加密?
無 - 響應(yīng)是否加密?
通過查看“響應(yīng)”模塊可以發(fā)現(xiàn),響應(yīng)數(shù)據(jù)是加密的
- cookie是否加密?
無
二、加密位置定位
1、看啟動(dòng)器
查看啟動(dòng)器發(fā)現(xiàn)里面包含異步,所以無法正確找到加密位置
2、搜索關(guān)鍵字
因?yàn)榧用軈?shù)是一整個(gè)密文,所以無法搜索關(guān)鍵字
3、hook
因?yàn)椤拜d荷”是一整個(gè)密文,所以網(wǎng)站大概率會(huì)使用JSON.stringify
將數(shù)據(jù)轉(zhuǎn)換為json字符串再進(jìn)行加密,所以我們可以hookJSON.stringify
,hook代碼:
var my_stringify = JSON.stringify;
JSON.stringify = function (params) {debuggerconsole.log("json_stringify params:",params);return my_stringify(params);
};
運(yùn)行hook代碼,再次點(diǎn)擊翻頁,發(fā)現(xiàn)可以斷住
接著調(diào)試執(zhí)行,我們就可以找到加密位置了,并且可以看到,在下面的回調(diào)方法中對響應(yīng)進(jìn)行了解密操作。
三、解決密鑰
1、分析網(wǎng)站密鑰的獲取
在定位到加密以及解密位置后,我們可以看到網(wǎng)站加解密時(shí)需要密鑰,并且網(wǎng)站的密鑰獲取是從本地存儲(chǔ)中獲取logo1
和logo2
所以我們可以通過hooklocalStorage.setItem
來找到網(wǎng)站是怎么生成的這兩個(gè)參數(shù)。
hook代碼:
var my_setItem = localStorage.setItem;
localStorage.setItem = function (key, value) {debuggerreturn my_setItem.call(localStorage, key, value);
};
同時(shí),為了讓網(wǎng)站可以再次生成這兩個(gè)參數(shù),我們需要先將本地存儲(chǔ)中的刪除。在控制臺(tái)中,進(jìn)入“應(yīng)用”這個(gè)標(biāo)簽頁,再點(diǎn)擊“本地存儲(chǔ)空間”,然后點(diǎn)擊清除按鈕,就可以清除了。
然后運(yùn)行hook腳本,點(diǎn)擊瀏覽器上方的后退按鈕。注意:此處不能刷新頁面,因?yàn)樗⑿马撁鎕ook代碼將不再運(yùn)行,同時(shí),此網(wǎng)站是在首頁向本地存儲(chǔ)中放入的參數(shù),所以我們要回退到首頁生成。
點(diǎn)擊回退后,發(fā)現(xiàn)可以斷住
接著調(diào)試執(zhí)行,我們就可以找到網(wǎng)站設(shè)置的位置了,同時(shí),可以發(fā)現(xiàn)這個(gè)位置好像是在一個(gè)回調(diào)中。
再次觀察發(fā)包,可以發(fā)現(xiàn)網(wǎng)站確實(shí)是從一個(gè)bj.css的響應(yīng)中提取的。所以我們就可以通過請求這個(gè)接口,按照網(wǎng)站的提取方法提取出密鑰,或者自己寫正則表達(dá)式將密鑰提取出來。
四、驗(yàn)證碼
1、獲取數(shù)據(jù)錯(cuò)誤
在扣完js之后,我們發(fā)送請求會(huì)發(fā)現(xiàn),獲取到的數(shù)據(jù)與網(wǎng)站抓包獲取到的數(shù)據(jù)不太一致,網(wǎng)站抓包獲取到的數(shù)據(jù)是一整個(gè)密文,而我們獲取到的數(shù)據(jù)是一個(gè)json數(shù)據(jù)并且code是511
此時(shí)我們再次回到網(wǎng)站,發(fā)現(xiàn)網(wǎng)站在收到code為511的響應(yīng)時(shí),會(huì)出現(xiàn)一個(gè)驗(yàn)證碼
2、處理驗(yàn)證碼
點(diǎn)擊刷新驗(yàn)證碼可以發(fā)現(xiàn),網(wǎng)站是發(fā)送一個(gè)請求cms/validateCode/undefined獲取的驗(yàn)證碼,響應(yīng)中的data
是base64編碼的圖片數(shù)據(jù)。
當(dāng)我們輸入一個(gè)錯(cuò)誤的驗(yàn)證碼時(shí),可以發(fā)現(xiàn),網(wǎng)站是將我們輸入的內(nèi)容拼接到路徑中進(jìn)行請求。
所以我們可以先請求undefined接口獲取到一個(gè)驗(yàn)證碼,然后破解驗(yàn)證碼(我是使用的第三方打碼平臺(tái)),將破解的驗(yàn)證碼拼接到路徑中,再次發(fā)送請求,然后再獲取數(shù)據(jù)即可。
五、扣js
將加密以及解密位置的代碼扣出,缺啥補(bǔ)啥即可。
該網(wǎng)站使用的是webpack,我們可以發(fā)現(xiàn),網(wǎng)站加密時(shí)使用的l
和m
都是來自于webpack中的模塊,
所以我們可以在f = n("e2b4")
打斷點(diǎn),然后進(jìn)入到n
方法中,扣出加載器,然后再將需要的模塊扣出即可。
六、源代碼
js源代碼因?yàn)樽謹(jǐn)?shù)太多無法上傳,所以就放在了資源中,在文章最上方點(diǎn)擊“立即下載”即可
python源碼:
"""
Email:912917367@qq.com
Date: 2023/8/29 11:41
"""
import timeimport execjs
import requestsfrom utils.chaojiying import ChaojiyingClientclass Spider:def __init__(self):self.session = requests.session()self.session.headers = {"MACHINE_CODE": str(int(time.time() * 1000)),"Origin": "https://www.cnpcbidding.com","Referer": "https://www.cnpcbidding.com/","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",}with open('reverse.js', 'r', encoding='utf-8') as f:self.js_obj = execjs.compile(f.read())self.bj = ''self.pic_str = ''def get_bj(self):url = "https://www.cnpcbidding.com/cms/css/bj.css"response = self.session.get(url)self.bj = response.textdef get_img_code(self):url = "https://www.cnpcbidding.com/cms/validateCode/undefined"response = self.session.get(url)cjy = ChaojiyingClient('lan8sjk', 'lan8@2023', '946014')pic_data = cjy.post_pic_base64(response.json()['data'], 6001)self.pic_str = pic_data['pic_str']url = "https://www.cnpcbidding.com/cms/validateCode/" + str(self.pic_str)response = self.session.get(url)print(response.text)print(response)def get_data(self):data = self.js_obj.call('get_params', self.bj)self.session.headers['Content-Type'] = "application/json;charset=UTF-8"url = "https://www.cnpcbidding.com/cms/article/page"response = self.session.post(url, data=data)data = self.js_obj.call('get_data', self.bj, response.text)print(data)if __name__ == '__main__':s = Spider()s.get_bj()s.get_img_code()s.get_data()