js逆向-产业政策大数据平台(调试保护,进制流参数加密, webpack)

声明:本文仅供学习交流,请勿暴力爬取数据,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

网站

调试保护

进入开发者工具,直接绕过内存溢出
进行控制台hook注入

1
2
3
4
5
6
7
Function.prototype.constructor_ = Function.prototype.constructor;
Function.prototype.constructor = function(a) {
if (a == "debugger") {
return function (){};
}
return Function.prototype.constructor_(a);
}

抓包

切换标签页抓包
负载2"*28@HP使用了进制流加密

定位加密位置和未加密的参数

查看请求调用堆栈,断点调试,调用堆栈中data已被加密
说明data在异步请求中被加密
alt text
在异步请求中找到加密前的参数,进入函数寻找加密逻辑
通过在控制台输出混淆代码定位到request的拦截器
axiosInstance[yM(679, 339, 486, 227, "C(TC") + yH(-169, -545, -648, "wCPA") + "rs"][yH(-534, -201, -232, "iY*&") + "st"][W1(-328, -529, -549, "7C66")]
定位到拦截器的末尾,断点调试查看拦截器的返回值,加密的参数为i.data
加密前的data

1
2
3
4
5
6
7
8
9
10
11
12
data = {
centralId: "",
city: "",
downtown: "",
garden: "",
homePageFlag: 1,
pageNum: 1,
pageSize: 7,
policyType: "4",
province: "",
sort: 0
}

加密位置
i[t(0, 1912, 0, "eXen", 1851)] = r[u(768, 833, 428, "@&x(") + "e"](i[c(432, -306, -315, 38, "wO#Q")])[c(310, -84, 522, 102, "T$0l") + "h"]()[l("^I&1", -341, -237, -231)]()
还原代码
PolicyInfoByTypeIdParam_encode(data).finish().slice()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//test.js
function PolicyInfoByTypeIdParam_encode(m,w){
if(!w)
//定义加载器后替换为w = jzq.Writer.create()
w=Writer.create()
if(m.policyType!=null&&Object.hasOwnProperty.call(m,"policyType"))
w.uint32(10).string(m.policyType)
if(m.centralId!=null&&Object.hasOwnProperty.call(m,"centralId"))
w.uint32(18).string(m.centralId)
if(m.province!=null&&Object.hasOwnProperty.call(m,"province"))
w.uint32(26).string(m.province)
if(m.city!=null&&Object.hasOwnProperty.call(m,"city"))
w.uint32(34).string(m.city)
if(m.downtown!=null&&Object.hasOwnProperty.call(m,"downtown"))
w.uint32(42).string(m.downtown)
if(m.garden!=null&&Object.hasOwnProperty.call(m,"garden"))
w.uint32(50).string(m.garden)
if(m.sort!=null&&Object.hasOwnProperty.call(m,"sort"))
w.uint32(56).uint32(m.sort)
if(m.pageNum!=null&&Object.hasOwnProperty.call(m,"pageNum"))
w.uint32(64).uint32(m.pageNum)
if(m.pageSize!=null&&Object.hasOwnProperty.call(m,"pageSize"))
w.uint32(72).uint32(m.pageSize)
if(m.homePageFlag!=null&&Object.hasOwnProperty.call(m,"homePageFlag"))
w.uint32(80).uint32(m.homePageFlag)
return w
}

缺少Writer.create, 全局搜索,Writer在webpack的模块中
没有Writer的直接定义函数
扣下整个加载器的代码,将加载器赋值给一个全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//test.js
//加载器
var jzq;
//函数中未定义,全局搜索得到
var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
//i2: webpack加载器
!function(g) {
var r2, e2, i2;
r2 = {...}, //省略3000行代码
e2 = {},
i2 = function e(t) {
var n = e2[t];
return n || r2[t][0].call(n = e2[t] = {
exports: {}
}, e, n, n.exports),
n.exports
}(16),
i2.util.global.protobuf = i2,
module && module.exports && (module.exports = i2)
jzq = i2;
}()

//加密函数
function main(data) {
return PolicyInfoByTypeIdParam_encode(data).finish().slice();
}

python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import requests
import execjs

cookies = {
'Hm_lvt_6146f11e5afab71309b3accbfc4a932e': '1725888175,1725948210,1726023361',
'Hm_lpvt_6146f11e5afab71309b3accbfc4a932e': '1726023361',
'HMACCOUNT': 'CBC9C4F6DD40A9B6',
'JSESSIONID': '14185E9C07B54031DB738E471A472E37',
}

headers = {
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Connection': 'keep-alive',
'Content-Type': 'application/octet-stream',
# 'Cookie': 'Hm_lvt_6146f11e5afab71309b3accbfc4a932e=1725888175,1725948210,1726023361; Hm_lpvt_6146f11e5afab71309b3accbfc4a932e=1726023361; HMACCOUNT=CBC9C4F6DD40A9B6; JSESSIONID=14185E9C07B54031DB738E471A472E37',
'Origin': 'https://www.spolicy.com',
'Referer': 'https://www.spolicy.com/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0',
'sec-ch-ua': '"Not)A;Brand";v="99", "Microsoft Edge";v="127", "Chromium";v="127"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
}

data = {
"centralId": "",
"city": "",
"downtown": "",
"garden": "",
"homePageFlag": 1,
"pageNum": 1,
"pageSize": 7,
"policyType": "2",
"province": "",
"sort": 0
}

with open('test.js', 'r', encoding='utf-8') as f:
jcode = f.read()

data = execjs.compile(jcode).call('main', data)
data = bytes(data['data'])
response = requests.post('https://www.spolicy.com/info_api/policyType/showPolicyType', cookies=cookies, headers=headers, data=data)
print(response.json())