逆向目的
‘{“code”:10004,“count”:null,“data”:null,“message”:“TOKEN已过期”}’
逆向过程
网址
https://jzsc.jst.zj.gov.cn/PublicWeb/index.html#/company
翻页网址
打断点
翻页
在该断点之前,token参数已经生成,因此在call stack里从上往下找token的生成方法
token=s,因此分析s的生成过程
i是一个时间戳
进入上图选择p.b里的这个app.28f742b的js文件,到以下加密的位置
utf8(unicode编码)
密码 *
255B675CDF21B04F923992E0E9F4A498
偏移量 *
255B675CDF21B04F
模式 *
CBC
填充 *
Pkcs7Padding
编码 *
Base64
AES加密
在线工具
https://www.ssleye.com/ssltool/aes_cipher.html
推荐一个加密博客
结果一致,说明token就是一个用AES加密的时间戳。
用js模拟出来就行
pip install PyExecJS
在node环境安装加密解密库crypto-js
npm install crypto-js
出现如下结果则安装成功
added 1 package, and audited 2 packages in 1s
found 0 vulnerabilities
var CryptoJS = require('crypto-js');
var a = new Date;
var i = new Date(a).getTime().toString()
// 一定要用utf8生成密钥,不然无法用java解密
// 长度128bit,192bit,256bit之一
var key = CryptoJS.enc.Utf8.parse('255B675CDF21B04F923992E0E9F4A498');
var iv = CryptoJS.enc.Utf8.parse('255B675CDF21B04F');
var cipher = CryptoJS.AES.encrypt(i, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
console.log(cipher.ciphertext.toString(CryptoJS.enc.Base64));
token1=cipher.ciphertext.toString(CryptoJS.enc.Base64)
import execjs
with open('aestest.js', 'r', encoding='utf-8') as f:
data = f.read()
docjs = execjs.compile(data) #用execjs编译返回的js代码
res = docjs.eval('a')
print(res)
res1 = docjs.eval('i')
print(res1)
token1 = docjs.eval('token1')
print(token1)
2022-10-03T11:01:17.582Z
1664794877638
JxietRwOtUgDB5g7HGRFNg==
import execjs
with open('aestest.js', 'r', encoding='utf-8') as f:
data = f.read()
docjs = execjs.compile(data) #用execjs编译返回的js代码
res = docjs.eval('a')
print(res)
res1 = docjs.eval('i')
print(res1)
token1 = docjs.eval('token1')
print(token1)
import requests
cookies = {
'Hm_lvt_a499288f9faf7b5e5c13c17092030489': '1663830112,1664503799,1664759096',
'Hm_lpvt_a499288f9faf7b5e5c13c17092030489': '1664760677',
}
headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Content-Type': 'application/json',
'Origin': 'https://jzsc.jst.zj.gov.cn',
'Pragma': 'no-cache',
'Referer': 'https://jzsc.jst.zj.gov.cn/PublicWeb/index.html',
'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/105.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
'sec-ch-ua': '"Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'token': token1,
'x-forwarded-for': '192.168.1.1',
}
params = (
('appKey', 'c9406731-50bc-4e23-b3f5-b7e7d3093875'),
('time', '1628557817533'),
('sign', '/OZ2b8tUcAgLQitEwk3Q3w=='),
)
data = '{"CertID":"","EndDate":"","Zzmark":"","City":"","COUNTY":"","pageIndex":7,"pageSize":10}'
# response = requests.post('https://jzsc.jst.zj.gov.cn/publishserver/ZJJGManagerWebApi/api/EnterpriseInfo/GetEnterpriseInfo', headers=headers, params=params, cookies=cookies, data=data)
#NB. Original query string below. It seems impossible to parse and
#reproduce query strings 100% accurately so the one below is given
#in case the reproduced version is not "correct".
response = requests.post('https://jzsc.jst.zj.gov.cn/publishserver/ZJJGManagerWebApi/api/EnterpriseInfo/GetEnterpriseInfo?appKey=c9406731-50bc-4e23-b3f5-b7e7d3093875&time=1628557817533&sign=%2FOZ2b8tUcAgLQitEwk3Q3w%3D%3D', headers=headers, cookies=cookies, data=data)
print(response.text)
{“code”:200,“Message”:“响应成功!”,“data”:[{“LEGALMANNAME”:“郑经杰”,“SCUCODE1”:“91330110MABXB6NR02”,“CORPCODE1”:“91330110MABXB6NR02”,“CORPNAME”:“杭州宜杰劳务有限公司”,“CITY”:“杭州市”,“COUNTY”:“余杭区”,“OPINIONDATETIME1”:“2022-09-15”,“OPINIONDATETIME”:“2022-09-15”,“SCUCODE”:“VrTPfdoWFT+IZnyhNj7WFOw7aQ1AMoCf35Wln/JVS1w=”,“CORPCODE”:“VrTPfdoWFT+IZnyhNj7WFOw7aQ1AMoCf35Wln/JVS1w=”},{“LEGALMANNAME”:“陈世清”,“SCUCODE1”:“91330802MABXUN3H12”,“CORPCODE1”:“91330802MABXUN3H12”,“CORPNAME”:“衢州盛珩建筑劳务有限公司”,“CITY”:“衢州市”,“COUNTY”:“柯城区”,“OPINIONDATETIME1”:“2022-09-14”,“OPINIONDATETIME”:“2022-09-14”,“SCUCODE”:“9Qt7qWyfxVWXjcEwsu+uTQm3v6etpnueasST/OjAncM=”,“CORPCODE”:“9Qt7qWyfxVWXjcEwsu+uTQm3v6etpnueasST/OjAncM=”},{“LEGALMANNAME”:“方小龙”,“SCUCODE1”:“91330122MABWFBC04Q”,“CORPCODE1”:“91330122MABWFBC04Q”,“CORPNAME”:“杭州红龙建筑劳务有限公司”,“CITY”:“杭州市”,“COUNTY”:“桐庐县”,“OPINIONDATETIME1”:“2022-09-14”,“OPINIONDATETIME”:“2022-09-14”,“SCUCODE”:“L5brDXNHm+2doJw9eK7FKrlDWaHlw1zcvHd82DK8ERA=”,“CORPCODE”:“L5brDXNHm+2doJw9eK7FKrlDWaHlw1zcvHd82DK8ERA=”
Process finished with exit code 0
补充说明
这里为什么没有用扣JS的方法,是因为jquery前端框架把js打包成webpack这种类型,导致这里函数依赖太多,扣起来太麻烦,因此既然知道加密的生成过程,因此用crypto-js模拟就行。