声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵犯了您的合法权益,请告知,我将及时更正、删除,谢谢。邮箱地址:[email protected]
文章目录:
一、项目准备
二、参数分析
三、静态调试
四、动态调试
五、堆栈跟踪
作者环境:win10,node.js
开发工具:WebStorm
目标网址: aHR0cHM6Ly93d3cuc2luYS5jb20uY24v
点击登录过后浏览器捕获到了多个数据包,我们可以通过响应内容中的数据判定那个才是我们想要的。
https://login---.com.cn--脱敏处理---1647765920689
图1
对于做登录分析的话,我们如何快速找到那个才是我们想要的数据包呢,根据我的个人经验总结①对于登录数据传输绝大部分都是POST请求②数据包名称中包含login这样的关键词③查看响应内容
接下来我们继续,我们顺利的根据上面的分析找到了响应内容如图2所示,内容的字符进行了unicode编码,我们做一个在线解码查看结果。可以看到对应的就是,登录名或密码错误
图2
图3
查看参数根据经验发现四个可疑参数su、servertime、nonce、sp
图4
经过静态分析调试我们知道了参数加密位置,在代码的名称道中我们也可以看到一些很熟悉的面孔,例如base64\RSAkey\setPublic在里面还掺杂着username\password这样的参数因此我们可以初步判断这就是加密位置,加密的算法是密码学中的RSA非对称加密。
图5
四、动态调试
通过断点动态调试我们可以发现,我们的账号和密码都是在这个位置进行加密的,对于username的结果我们是可以直接和图4中完全吻合的,密码部分是因为RAS加密的特性他的结果必然是对不上的,我们暂时可以忽略。
图6
五、堆栈跟踪(根据加密参数进行图解,加密代码全部做了脱敏处理,只截取了关键部分)-想要进一步了解学习可以在公众号留言
--------------------------su加密--------------------------
1.su - 针对账号进行加密
图7 定位到加密函数扣出代码本地生成
base64 = {
encode: function(n) {
n = "" + n;
if (n == "") {
return ""
}
var l = "";
var u, s, q = "";
var t, r, p, o = "";
var m = 0;
do {
u = n.charCodeAt(m++);
s = n.charCodeAt(m++);
q = n.charCodeAt(m++);
t = u >> 2;
r = ((u & 3) << 4) | (s >> 4);
p = ((s & 15) << 2) | (q >> 6);
o = q & 63;
if (isNaN(s)) {
p = o = 64
} else {
if (isNaN(q)) {
o = 64
}
}
l = l + this._keys.charAt(t) + this._keys.charAt(r) + this._keys.charAt(p) + this._keys.charAt(o);
u = s = q = "";
t = r = p = o = ""
} while (m < n.length);
return l
}
},
_keys: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
_keys_urlsafe: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
_subp_v2_keys: "uAL715W8e3jJCcNU0lT_FSXVgxpbEDdQ4vKaIOH2GBPtfzqsmYZo-wRM9i6hynrk=",
_subp_v3_keys_3: "5WFh28sGziZTeS1lBxCK-HgPq9IdMUwknybo.LJrQD3uj_Va7pE0XfcNR4AOYvm6t"
};
console.log(base64.encode("113222222"))
图8 定位到加密位置寻找加密函数
图9 寻找到加密函数 本地生成
2.nonce - 随机生成固定位数字符串
// len = 你想要生成多少位的随机组合结果----- 该加密写死了6位
var makeNonce = function(len) {
var x = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var str = "";
for (var i = 0; i < len; i++) {
str += x.charAt(Math.ceil(Math.random() * 1000000) % x.length)
}
return str
};
console.log(makeNonce(6))
3.sp - 对servertime时间戳 + nonce随机字符串 + 密码 进行加密
图10 跟踪到生成raskey
图11 生成key后与参数一起进行加密
在本地调试rsa加密时内部会有检查navigator中的appName、appVersion参数需要自己本地构造。
navigator = {
appName: "Netscape",
appVersion: "5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
}, window = this, window.navigator = navigator;
sinaSSOEncoder = {
"base64": {
"_keys": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
"_keys_urlsafe": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
"_subp_v2_keys": "uAL715W8e3jJCcNU0lT_FSXVgxpbEDdQ4vKaIOH2GBPtfzqsmYZo-wRM9i6hynrk=",
"_subp_v3_keys_3": "5WFh28sGziZTeS1lBxCK-HgPq9IdMUwknybo.LJrQD3uj_Va7pE0XfcNR4AOYvm6t"
},
"Cookie": {},
"getSUBPCookie": {},
"n": null,
"e": 0,
"d": null,
"p": null,
"q": null,
"dmp1": null,
"dmq1": null,
"coeff": null
}
!(function() {
var av;
var ah = 244837814094590;
var Y = ((ah & 16777215) == 15715070);
function aq(z, t, az) {
if (z != null) {
if ("number" == typeof z) {
this.fromNumber(z, t, az)
} else {
if (t == null && "string" != typeof z) {
this.fromString(z, 256)
} else {
function S() {
d(new Date().getTime())
}
if (T == null) {
T = new Array();
ab = 0;
var I;
if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto && typeof (window.crypto.random) === "function") {
var F = window.crypto.random(32);
for (I = 0; I < F.length; ++I) {
T[ab++] = F.charCodeAt(I) & 255
}
}
while (ab < M) {
I = Math.floor(65536 * Math.random());
T[ab++] = I >>> 8;
T[ab++] = I & 255
}
ab = 0;
S()
}
function L() {
this.n = null;
this.e = 0;
this.d = null;
this.p = null;
this.q = null;
this.dmp1 = null;
this.dmq1 = null;
this.coeff = null
}
function o(z, t) {
if (z != null && t != null && z.length > 0 && t.length > 0) {
this.n = g(z, 16);
this.e = parseInt(t, 16)
} else {
alert("Invalid RSA public key")
}
}
function V(t) {
return t.modPowInt(this.e, this.n)
}
function p(az) {
var t = ae(az, (this.n.bitLength() + 7) >> 3);
if (t == null) {
return null
}
var aA = this.doPublic(t);
if (aA == null) {
return null
}
var z = aA.toString(16);
if ((z.length & 1) == 0) {
return z
} else {
return "0" + z
}
}
L.prototype.doPublic = V;
L.prototype.setPublic = o;
L.prototype.encrypt = p;
this.RSAKey = L
}
).call(sinaSSOEncoder);
最终输出结果: