抓包发现 这个post请求 如下
可以发现post请求的参数变成一堆奇怪的字符串
这样的话 就没办法分析具体有哪些参数了
接着我就解了下这个加密的过程
首先url上带了 参数 rcuuid 和rcdesc
可以发现 rcdesc是个固定值 “提交一个Query进行计算” 然后rcuuid是个变值 应该是随机生成的uuid
然后再看下面那个 request payload 里面本应该是一串json格式数据 然而就是被加密了
那就来解下 开始
首先就看看它发ajax请求的时候这步
这里就已经能初步推断出post的参数data就是这个了 只不过发请求的时候被加密了
那我们就在发ajax的时候打个断点
可以发现这个w就是加密后的值
那么这个w怎么来的
继续往上看
w = function(e, t) {
return e ? "string" == typeof e ? e : p === g || "GET" == t ? he(e) : JSON.stringify(e) : null
}(s.data, y)
结合上面代码分析,其实意思就是把这个s.data (就是post请求的参数)变成json字符串发送post请求 基本可以确定了
那我们具体来看看这个w怎么生成
找下调用栈
在me这个调用栈 可以发现 w是通过 o.LZString.compressToBase64(w)
这个函数生成的
看到了熟悉的base64 但这里肯定不是用的原生的base64 肯定是改动过的
接着就看这个方法怎么实现的
找到函数的位置
就是这个函数了 这段代码意思是 再把这个data传到另一个加密函数
var n = o.LZString._compress(r, 6, function(r) {
return t.charAt(r)
});
这个里面的n就是返回的加密字符串
后面就是根据这个加密字符串长度 根据4的余数 在字符串最后拼接有多少个=号
所以上面那段加密其实也不是真正的加密,,只是对加密的字符串末尾加上不同数量的=号罢了
那么我们再看看里面这个函数
o.LZString._compress(r, 6, function(r) {
return t.charAt(r)
})
有三个参数 第一个就是参数data,第二个参数是固定数字6,第三个参数是一个函数
找到这个函数的位置
_compress: function(r, o, n) {
if (null == r)
return "";
var t, e, i, s = {}, p = {}, c = "", u = "", a = "", l = 2, f = 3, h = 2, d = [], m = 0, g = 0;
for (i = 0; i < r.length; i += 1)
if (c = r.charAt(i),
Object.prototype.hasOwnProperty.call(s, c) || (s[c] = f++,
p[c] = !0),
u = a + c,
Object.prototype.hasOwnProperty.call(s, u))
a = u;
else {
if (Object.prototype.hasOwnProperty.call(p, a)) {
if (a.charCodeAt(0) < 256) {
for (t = 0; t < h; t++)
m <<= 1,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++;
for (e = a.charCodeAt(0),
t = 0; t < 8; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1
} else {
for (e = 1,
t = 0; t < h; t++)
m = m << 1 | e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e = 0;
for (e = a.charCodeAt(0),
t = 0; t < 16; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1
}
0 == --l && (l = Math.pow(2, h),
h++),
delete p[a]
} else
for (e = s[a],
t = 0; t < h; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1;
0 == --l && (l = Math.pow(2, h),
h++),
s[u] = f++,
a = String(c)
}
if ("" !== a) {
if (Object.prototype.hasOwnProperty.call(p, a)) {
if (a.charCodeAt(0) < 256) {
for (t = 0; t < h; t++)
m <<= 1,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++;
for (e = a.charCodeAt(0),
t = 0; t < 8; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1
} else {
for (e = 1,
t = 0; t < h; t++)
m = m << 1 | e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e = 0;
for (e = a.charCodeAt(0),
t = 0; t < 16; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1
}
0 == --l && (l = Math.pow(2, h),
h++),
delete p[a]
} else
for (e = s[a],
t = 0; t < h; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1;
0 == --l && (l = Math.pow(2, h),
h++)
}
for (e = 2,
t = 0; t < h; t++)
m = m << 1 | 1 & e,
g == o - 1 ? (g = 0,
d.push(n(m)),
m = 0) : g++,
e >>= 1;
for (; ; ) {
if (m <<= 1,
g == o - 1) {
d.push(n(m));
break
}
g++
}
return d.join("")
},
可以发现这个才是真正的加密函数
抠出这个函数 先在浏览器试试运行下
可以发现是一样的,,那么加密函数就是这个了 后面就是根据这个字符串长度取4的余数来添加=号了
我再在node上模拟下 看看结果会变不
首先扣出函数的js代码 试着改一下 因为第三个参数是一个函数
我们用python调用js的话是不能直接传函数的
那么这里就直接把这个函数写死吧
可以发现也是一模一样的
好了 data加密已经解出来了。
接着分析下具体的参数
这里面有一个limit offset 很明显就是用来翻页的 下面再加了个时间戳
`{"query":{"resid":"/SCHSJC/app/hsjc.app/jcjg/hscxfx/cyxxcx_20220427yh.spg","fields":[{"name":"CALCULATOR_2"},{"name":"JCJGOU"},{"name":"SGTXM"},{"name":"ZJLX"},{"name":"ZJHM"},{"name":"XM"},{"name":"XB"},{"name":"CYRQ"},{"name":"LXFS"},{"name":"JCLX"},{"name":"QMJCID"},{"name":"JCRQ"},{"name":"YBLX"},{"name":"JCJG"},{"name":"HSJCLX"},{"name":"CYDD"},{"name":"CYRY"},{"name":"XZQH"},{"name":"SSRQ"},{"name":"JCPC"},{"name":"HYFS"},{"name":"XS"}],"sources":null,"select":true,"filter":[],"params":[{"name":"fieldsFilter1","value":"[{\\"clauses\\":[{\\"leftExp\\":\\"CYRQ\\",\\"operator\\":\\"=\\",\\"rightValue\\":\\"20220612\\"}]}]"},{"name":"combobox2","value":"2"}],"sort":[],"options":{"needCodeDesc":true,"autoSort":true,"cache":true,"limit":20,"offset":20,"queryBlobFlag":true,"queryTotalRowCount":false,"needHighlightKeyword":true,"highlightPreTag":"<em class='sz-keyword'>","highlightPostTag":"</em>"},"queryId":"model3","resModifyTime":1651852697419},"resid":"/SCHSJC/app/hsjc.app/jcjg/hscxfx/cyxxcx_20220427yh.spg"}`
其他的应该都是些定值
带上这个加密字符串请求 可以看到成功了!