一、数据接口分析
主页地址:某矿
1、抓包
通过抓包可以发现数据接口是cgxj/by-lx-page
2、判断是否有加密参数
- 请求参数是否加密?
通过查看“载荷”模块可以发现有一个param
的加密参数
- 请求头是否加密?
无 - 响应是否加密?
无 - cookie是否加密?
无
二、加密位置定位
1、看启动器
查看启动器发现里面有一个index.js中的匿名调用堆栈,点进去查看
点进去后发现,网站确实是在此处发送的请求,而且参数param
也是在此处赋值。但是param
的值来自于A.sent
,此处找不到A.sent
赋值的位置,所以此处只是发包位置,并不是加密位置。
2、搜索关键字
通过搜索sent
相关的关键字,不能有效的定位到加密位置
3、hook
因为请求参数中只有一个param
密文参数,所以网站大概率会使用JSON.stringify
将数据转换为json字符串再进行加密,所以我们可以hookJSON.stringify
,hook代码:
var my_stringify = JSON.stringify;
JSON.stringify = function (params) {
debugger
console.log("json_stringify params:",params);
return my_stringify(params);
};
运行hook代码,再次获取数据,发现可以断住
接着调试执行,就可以发现加密位置
但是,此时我们并不能确定此处的加密结果是否就是发包时使用的A.sent
,所以我们可以在发包位置再打上断点,并将此处断点放开,通过对比,我们可以发现,此处的加密结果就是发包时使用的。
三、扣js代码
将加密位置的代码扣出,缺啥补啥即可。
注意,加密时使用的RSA加密以及md5加密,均可使用标准模块,但是RSA加密时,要补一下网站的encryptLong
方法,同时RSA加密所使用的公钥,通过观察发包可以看出,网站每次获取数据前,都会先发一个包获取公钥。
所以先请求public接口获取到公钥,再进行加密即可。
JavaScript源码:
const JSEncrypt = require('jsencrypt');
const CryptoJS = require("crypto-js");
function w(A) {
var e, t, n = "", r = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", a = "=";
for (e = 0; e + 3 <= A.length; e += 3)
t = parseInt(A.substring(e, e + 3), 16),
n += r.charAt(t >> 6) + r.charAt(63 & t);
e + 1 == A.length ? (t = parseInt(A.substring(e, e + 1), 16),
n += r.charAt(t << 2)) : e + 2 == A.length && (t = parseInt(A.substring(e, e + 2), 16),
n += r.charAt(t >> 2) + r.charAt((3 & t) << 4));
while ((3 & n.length) > 0)
n += a;
return n
}
JSEncrypt.prototype.encryptLong = function (A) {
var e = this.getKey()
, t = (e.n.bitLength() + 7 >> 3) - 11;
var n = ""
, r = "";
if (A.length > t)
return n = A.match(/.{1,50}/g),
n.forEach((function (A) {
var t = e.encrypt(A);
r += t
}
)),
w(r);
var a = e.encrypt(A)
, s = w(a);
return s
}
function b(A, e, t) {
return e in A ? Object.defineProperty(A, e, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : A[e] = t,
A
}
function d(A, e) {
var t = Object.keys(A);
if (Object.getOwnPropertySymbols) {
var n = Object.getOwnPropertySymbols(A);
e && (n = n.filter((function (e) {
return Object.getOwnPropertyDescriptor(A, e).enumerable
}
))),
t.push.apply(t, n)
}
return t
}
function m(A) {
for (var e = 1; e < arguments.length; e++) {
var t = null != arguments[e] ? arguments[e] : {};
e % 2 ? d(Object(t), !0).forEach((function (e) {
b(A, e, t[e])
}
)) : Object.getOwnPropertyDescriptors ? Object.defineProperties(A, Object.getOwnPropertyDescriptors(t)) : d(Object(t)).forEach((function (e) {
Object.defineProperty(A, e, Object.getOwnPropertyDescriptor(t, e))
}
))
}
return A
}
function get_param(pub_key) {
var e = {
"inviteMethod": "",
"businessClassfication": "",
"mc": "",
"lx": "CGGG",
"dwmc": "",
"pageIndex": 1
}
var t = new JSEncrypt();
t.setPublicKey(pub_key)
a = m(m({}, e), {}, {
sign: CryptoJS.MD5(JSON.stringify(e)).toString(),
timeStamp: +new Date
})
return t.encryptLong(JSON.stringify(a))
}