声明:案例分析仅供学习交流使用,勿用于任何非法用途。如学习者进一步逆向并对版权方造成损失,请自行承担法律后果,本人概不负责。
首先查看其登陆POST请求,这里随机输入密码【123456789】,显然用户名、密码等信息被加密成了jsonKey字段作为参数:
从调用栈往上跟,最终找到 tiananapp/customer_login/taPcLogin POST中明文->密文的地方:
此处的 newEncrypt() 函数如下:
//传入的l为:
//"{"body":{"loginMethod":"1","name":"13823571234","password":"123456789"},"head":{"userCode":null,"channelCode":"101","transTime":1618970697277,"transToken":"","customerId":null,"transSerialNumber":""}}"
l.prototype.newEncrypt = function(l) {
var n = p.enc.Utf8.parse(this.privaKey)
, t = p.enc.Utf8.parse(this.privaKey)
, e = p.enc.Utf8.parse(l)
, a = p.AES.encrypt(e, n, {
iv: t,
mode: p.mode.CBC,
padding: p.pad.Pkcs7
});
return p.enc.Base64.stringify(a.ciphertext)
}
显然,获得了上面的 p,就可以获得登陆加密模块,而p是通过 t(“模块名”) 形式加载:
t(“模块名”)函数源码:
function f(r) {
if (n[r])
return n[r].exports;
var t = n[r] = {
i: r,
l: !1,
exports: {}
};
return e[r].call(t.exports, t, t.exports, f),
t.l = !0,
t.exports
}
直接拿出这个函数是无用的,毕竟涉及到模块间的互相引用,于是可以把其他Webpack相关模块拿出来。首先在runtime.85b741a7d19631648246.js中把加载模块的 f() 函数赋值成全局变量:
var module; //用全局的module拿到f(),便于我们的测试页面使用
!function(e) {
... 省略 ...
function f(r) {
if (n[r]) return n[r].exports;
var t = n[r] = {
i: r,
l: !1,
exports: {}
};
return e[r].call(t.exports, t, t.exports, f), t.l = !0, t.exports
}
module = f;
... 省略 ...
}([]);
测试网页中使用 module(“NFKh”) 拿到加密模块,进而得到jsonKey字段生成方式:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>测试页面</title>
</head>
<body>
<!-- 注释掉无关且报错的保证程序正常执行 -->
<script type="text/javascript" src="runtime.85b741a7d19631648246.js"></script>
<!-- <script type="text/javascript" src="polyfills.52e77c4406a4fef4ab17.js"></script> -->
<script type="text/javascript" src="vendor.7e178057f36014b4b175.js"></script>
<!-- <script type="text/javascript" src="main.b0f015e4e6cf52015ff3.js"></script> -->
<script>
let p = module("NFKh");
function getAesKey(l) {
l = l || 32;
for (var n = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678", t = n.length, e = "", a = 0; a < l; a++)
e += n.charAt(Math.floor(Math.random() * t));
return e
}
let key = getAesKey(16);
function newEncrypt(l) {
var n = p.enc.Utf8.parse(key),
t = p.enc.Utf8.parse(key),
e = p.enc.Utf8.parse(l),
a = p.AES.encrypt(e, n, {
iv: t,
mode: p.mode.CBC,
padding: p.pad.Pkcs7
});
return p.enc.Base64.stringify(a.ciphertext)
}
console.log(newEncrypt('{"body":{"loginMethod":"1","name":"13823571234","password":"123456789"},"head":{"userCode":null,"channelCode":"101","transTime":1618970697277,"transToken":"","customerId":null,"transSerialNumber":""}}'));
</script>
</body>
</html>
调用上面的方法,当提交的字串和随机生成的key相同时,可以的官方网站得到相同的jsonKey字段。