一、数据接口分析
主页地址:某蜂窝
1、抓包
通过抓包可以发现数据是静态的,在html中。
2、判断是否有加密参数
- 请求参数是否加密?
无 - 请求头是否加密?
无 - 响应是否加密?
无 - cookie是否加密?
通过查看“cookie”模块,可以发现cookie中携带了加密参数__jsl_clearance_s
和__jsluid_s
二、加密位置定位
1、分析
因为是请求静态页面时携带了cookie,所以肯定在这个请求之前还有其他请求,在“应用”模块中,将cookie全部清除
再次刷新页面,观察抓包,可以发现,在获取到正常的html页面之前,网站获取到了两个状态码是521的响应。
但是在“响应”模块中无法加载响应数据,所以我们可以使用Python发包,看看返回的响应是什么。可以发现,第一次请求,网站返回的响应中,是一段js代码,而且可以看出是设置cookie中的__jsl_clearance_s
参数的,同时响应头中还设置了__jsluid_s
参数,而且这个js代码只是一段简单的字符拼接。
携带这两个cookie,再次发送请求,可以发现,网站返回的还是js代码,而且这次的js代码还是混淆的。
我们将响应的js代码放入到js文件中,再使用ast解混淆可以发现,在这段js代码中重新设置了cookie中的__jsl_clearance_s
参数,cookie值的生成是使用的_0xa4b0eb
方法(每次请求方法名可能会不同,根据位置找即可)。
所以我们将_0xa4b0eb
方法扣出,在_0xa4b0eb
方法中还用到了一个hash
,同样将hash
扣出即可。运行代码,发现可以生成cookie值。
但是,当我们通过请求调用js进行生成可以发现,有时候可以生成,有时候又生成不了。这个时候我们对比传入方法中的ha
的值可以发现,可以生成的是sha1
,生成不了的是md5
还有sha256
。再对比代码可以发现,ha
的值不同,hash
这个方法也不同,所以我们就需要根据ha
的值,进行处理。同时可以怀疑hash
这个方法就是md5加密或者sha加密。
这时,我们就需要验证一下,hash
是不是标准的加密算法。我们将cookie清空,同时勾选上“事件监听器断点”中的“脚本”,再次刷新页面。
等断到上方分析的这个js代码段的时候,往下找到hash
方法的调用位置,hash
方法有时候可能会混淆,可以根据代码结构找到大概位置,下断点。断住之后,在控制台中调用hash
方法加密字符串'1'
,再拉到源代码最底部,查看ha
的值,发现是sha256
,同时hash
加密出的密文,与标准模块一致。同样的步骤,可以验证出md5与sha1都是标准算法,所以可以将hash
方法使用标准模块代替。
三、源代码
JavaScript源码:
const CryptoJS = require('crypto-js')
var _0x442d45 = new Date();
function _0x29a569(_0x4c0f0f, _0x4ac451, _0xff3a7) {
var _0x2aba4e = _0xff3a7["chars"]["length"];
for (var _0x5e8fd5 = 0; _0x5e8fd5 < _0x2aba4e; _0x5e8fd5++) {
for (var _0x32eaed = 0; _0x32eaed < _0x2aba4e; _0x32eaed++) {
var _0x2f5939 = _0x4ac451[0] + _0xff3a7["chars"]["substr"](_0x5e8fd5, 1) + _0xff3a7["chars"]["substr"](_0x32eaed, 1) + _0x4ac451[1];
var hash;
switch (_0xff3a7['ha']) {
case 'md5': {
hash = CryptoJS.MD5
break;
}
case 'sha256': {
hash = CryptoJS.SHA256
break
}
case 'sha1': {
hash = CryptoJS.SHA1
break
}
}
if (hash(_0x2f5939).toString() == _0x4c0f0f) {
return [_0x2f5939, new Date() - _0x442d45];
}
}
}
}
function get_cookie(_0xff3a7) {
return _0x29a569(_0xff3a7['ct'], _0xff3a7["bts"], _0xff3a7);
}
python源码:
"""
Email:912917367@qq.com
Date: 2023/9/7 11:27
"""
import json
import re
import execjs
import requests
class Spider:
def __init__(self):
self.session = requests.session()
self.session.headers = {
"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",
'authority': 'www.mafengwo.cn',
'referer': 'https://www.mafengwo.cn/',
}
with open('reverse.js', 'r', encoding='utf-8') as f:
self.js_obj = execjs.compile(f.read())
def send1(self):
response = self.session.get('https://www.mafengwo.cn/i/24326610.html')
cookie = re.findall(r"document.cookie=(.*?);location.href", response.text)[0]
cookie = self.js_obj.eval(cookie).split(';')[0]
cookie_list = cookie.split('=')
self.session.cookies[cookie_list[0]] = cookie_list[1]
def send2(self):
response = self.session.get('https://www.mafengwo.cn/i/24326610.html')
go = re.findall(r';go\((.*?)\)</script>', response.text)[0]
go = json.loads(go)
cookie = self.js_obj.call('get_cookie', go)
self.session.cookies[go['tn']] = cookie[0]
def send3(self):
response = self.session.get('https://www.mafengwo.cn/i/24326610.html')
print(response.text)
if __name__ == '__main__':
s = Spider()
s.send1()
s.send2()
s.send3()