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在异步请求中被加密

在异步请求中找到加密前的参数,进入函数寻找加密逻辑
通过在控制台输出混淆代码定位到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
| function PolicyInfoByTypeIdParam_encode(m,w){ if(!w) 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
|
var jzq;
var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
!function(g) { var r2, e2, i2; r2 = {...}, 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', '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())
|