声明
本文仅供学习参考,如有侵权可私信本人删除,请勿用于其他途径,违者后果自负!
如果觉得文章对你有所帮助,可以给博主点击关注和收藏哦!
前言
目标网站:aHR0cHM6Ly9tZGZnaGcuNXhwb2lqaHRmLmNvbS9kZWZhdWx0Lmh0bWwjLw==
接口:auth.login
参数分析
进入网站后点击登录,会有一个简单的验证码,输入之后才会提交登录参数。
可以看到这个参数很长,肉眼也看不懂不知道是什么东西,毫无疑问是进行了加密。
由于之前我已经分析过了网站,所以直接搜索json=
即可定位到加密位置。
ps:最近发现在更新了新版本的谷歌后使用F12的搜索很多内容都搜索不到,上网查了查资料。
然后重启就可以了。
继续回归正题,通过关键字定位后:
观察代码后分别打上断点,重新触发。
单步调试,执行u
函数。
一个JSON.stringify的功能,console中输出的参数信息密码是进行了加密,还获取了输入的验证码及验证码id,肯定是要拿到后端进行校验。
通过反复调试发现saltedPassword是动态变化的,截图中的盐值也能够看到这一点。
那么现在的需求就比较明确了,首先将输入的明文密码加密,然后再组装成一个对象,进行一堆乱七八糟的计算当做参数提交由后端验证。
首先查看密码的加密算法,搜索一下关键字。
盐就是当前时间戳,token是密文密码,进行了sha1加盐的双重哈希。(算法见下文)
搞清楚了密码的算法后,就到了登陆提交的表单参数了,其中id值为:
比较简单,没什么说的。
跟了一遍u
函数发现还是一个JSON.stringify
的操作。
继续就到了加密表单数据的位置:
js
E = "json=" + Object(m.a)(l.a.stringify(_).slice(5)) + "|" + t.id;
剩下的就是单步然后把代码抠出来,直接放在最下面了。
算法还原
直接把代码拉下来就可以使用
js
var r = "="
, i = 8;
function a(t, e) {
t[e >> 5] |= 128 << 24 - e % 32,
t[15 + (e + 64 >> 9 << 4)] = e;
for (var n = Array(80), r = 1732584193, i = -271733879, a = -1732584194, c = 271733878, _ = -1009589776, l = 0; l < t.length; l += 16) {
for (var h = r, f = i, g = a, p = c, m = _, y = 0; y < 80; y++) {
n[y] = y < 16 ? t[l + y] : d(n[y - 3] ^ n[y - 8] ^ n[y - 14] ^ n[y - 16], 1);
var E = u(u(d(r, 5), o(y, i, a, c)), u(u(_, n[y]), s(y)));
_ = c,
c = a,
a = d(i, 30),
i = r,
r = E
}
r = u(r, h),
i = u(i, f),
a = u(a, g),
c = u(c, p),
_ = u(_, m)
}
return Array(r, i, a, c, _)
}
function o(t, e, n, r) {
return t < 20 ? e & n | ~e & r : t < 40 ? e ^ n ^ r : t < 60 ? e & n | e & r | n & r : e ^ n ^ r
}
function s(t) {
return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514
}
function u(t, e) {
var n = (65535 & t) + (65535 & e);
return (t >> 16) + (e >> 16) + (n >> 16) << 16 | 65535 & n
}
function d(t, e) {
return t << e | t >>> 32 - e
}
function c(t) {
for (var e = Array(), n = (1 << i) - 1, r = 0; r < t.length * i; r += i)
e[r >> 5] |= (t.charCodeAt(r / i) & n) << 32 - i - r % 32;
return e
}
function _(t) {
for (var e = "", n = 0; n < 4 * t.length; n += 3)
for (var i = (t[n >> 2] >> 8 * (3 - n % 4) & 255) << 16 | (t[n + 1 >> 2] >> 8 * (3 - (n + 1) % 4) & 255) << 8 | t[n + 2 >> 2] >> 8 * (3 - (n + 2) % 4) & 255, a = 0; a < 4; a++)
8 * n + 6 * a > 32 * t.length ? e += r : e += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(i >> 6 * (3 - a) & 63);
return e
}
var encode = {
Encode: function () {
var t = this
, e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
this.encodeBase64 = function (t) {
var n, r, i, a, o, s, u, d = "", c = 0;
for (t = function (t) {
t = t.replace(/\r\n/g, "\n");
for (var e = "", n = 0; n < t.length; n++) {
var r = t.charCodeAt(n);
r < 128 ? e += String.fromCharCode(r) : r > 127 && r < 2048 ? (e += String.fromCharCode(r >> 6 | 192),
e += String.fromCharCode(63 & r | 128)) : (e += String.fromCharCode(r >> 12 | 224),
e += String.fromCharCode(r >> 6 & 63 | 128),
e += String.fromCharCode(63 & r | 128))
}
return e
}(t); c < t.length;)
a = (n = t.charCodeAt(c++)) >> 2,
o = (3 & n) << 4 | (r = t.charCodeAt(c++)) >> 4,
s = (15 & r) << 2 | (i = t.charCodeAt(c++)) >> 6,
u = 63 & i,
isNaN(r) ? s = u = 64 : isNaN(i) && (u = 64),
d = d + e.charAt(a) + e.charAt(o) + e.charAt(s) + e.charAt(u);
return d
},
this.encodeSha1 = function (t) {
return _(a(c(e = t), e.length * i));
var e
},
this.encodePsw = function (e) {
var n = (new Date).getTime();
return {
salt: n,
token: t.encodeSha1(t.encodeSha1(e) + n)
}
}
}
};
var myA = new encode.Encode()
result = myA.encodePsw('明文密码')
console.log(result)
生成id代码:
js
function getIdentity() {
return (new Date).getTime().toString().slice(2) + "" + Math.floor(900 * Math.random() + 100) + __WEBPACK_IMPORTED_MODULE_13__store__.a.getters.uid // __WEBPACK_IMPORTED_MODULE_13__store__.a.getters.uid = ''
}
l.a.stringify(_)代码:
js
function u_ (e, n, i, o, a, u, c, f, l, d, h, p) {
var v = e;
var s = {
"delimiter": "&",
"encode": true,
"encodeValuesOnly": false,
"skipNulls": false,
"strictNullHandling": false,
encoder:function(t) {
if (0 === t.length)
return t;
for (var e = "string" == typeof t ? t : String(t), n = "", r = 0; r < e.length; ++r) {
var o = e.charCodeAt(r);
45 === o || 46 === o || 95 === o || 126 === o || o >= 48 && o <= 57 || o >= 65 && o <= 90 || o >= 97 && o <= 122 ? n += e.charAt(r) : o < 128 ? n += i[o] : o < 2048 ? n += i[192 | o >> 6] + i[128 | 63 & o] : o < 55296 || o >= 57344 ? n += i[224 | o >> 12] + i[128 | o >> 6 & 63] + i[128 | 63 & o] : (r += 1,
o = 65536 + ((1023 & o) << 10 | 1023 & e.charCodeAt(r)),
n += i[240 | o >> 18] + i[128 | o >> 12 & 63] + i[128 | o >> 6 & 63] + i[128 | 63 & o])
}
return n
},
serializeDate: function(t) {
return a.call(t)
}
}
if ("function" == typeof c)
v = c(n, v);
else if (v instanceof Date)
v = d(v);
else if (null === v) {
if (o)
return u && !p ? u(n, s.encoder) : n;
v = ""
}
if ("string" == typeof v || "number" == typeof v || "boolean" == typeof v || r.isBuffer(v))
return u ? [h(p ? n : u(n, s.encoder)) + "=" + h(u(v, s.encoder))] : [h(n) + "=" + h(String(v))];
var m, g = [];
if (void 0 === v)
return g;
if (Array.isArray(c))
m = c;
else {
var y = Object.keys(v);
m = f ? y.sort(f) : y
}
for (var w = 0; w < m.length; ++w) {
var b = m[w];
a && null === v[b] || (g = Array.isArray(v) ? g.concat(t(v[b], i(n, b), i, o, a, u, c, f, l, d, h, p)) : g.concat(t(v[b], n + (l ? "." + b : "[" + b + "]"), i, o, a, u, c, f, l, d, h, p)))
}
return g
};
array_i = function() {
for (var t = [], e = 0; e < 256; ++e)
t.push("%" + ((e < 16 ? "0" : "") + e.toString(16)).toUpperCase());
return t
}();
function l_a_stringify(t, e) {
var i = {
default: "RFC3986",
formatters: {
RFC1738: function(t) {
return r.call(t, i, "+")
},
RFC3986: function(t) {
return t
}
},
RFC1738: "RFC1738",
RFC3986: "RFC3986"
};
var o ={
brackets: function(t) {
return t + "[]"
},
indices: function(t, e) {
return t + "[" + e + "]"
},
repeat: function(t) {
return t
}
}
var a = Date.prototype.toISOString;
var s = {
"delimiter": "&",
"encode": true,
"encodeValuesOnly": false,
"skipNulls": false,
"strictNullHandling": false,
encoder:function(t) {
if (0 === t.length)
return t;
for (var e = "string" == typeof t ? t : String(t), n = "", r = 0; r < e.length; ++r) {
var o = e.charCodeAt(r);
45 === o || 46 === o || 95 === o || 126 === o || o >= 48 && o <= 57 || o >= 65 && o <= 90 || o >= 97 && o <= 122 ? n += e.charAt(r) : o < 128 ? n += array_i[o] : o < 2048 ? n += array_i[192 | o >> 6] + array_i[128 | 63 & o] : o < 55296 || o >= 57344 ? n += array_i[224 | o >> 12] + array_i[128 | o >> 6 & 63] + array_i[128 | 63 & o] : (r += 1,
o = 65536 + ((1023 & o) << 10 | 1023 & e.charCodeAt(r)),
n += array_i[240 | o >> 18] + array_i[128 | o >> 12 & 63] + array_i[128 | o >> 6 & 63] + array_i[128 | 63 & o])
}
return n
},
serializeDate: function(t) {
return a.call(t)
}
}
var n = t
, a = e ? r.assign({}, e) : {};
if (null !== a.encoder && void 0 !== a.encoder && "function" != typeof a.encoder)
throw new TypeError("Encoder has to be a function.");
var c = void 0 === a.delimiter ? s.delimiter : a.delimiter
, f = "boolean" == typeof a.strictNullHandling ? a.strictNullHandling : s.strictNullHandling
, l = "boolean" == typeof a.skipNulls ? a.skipNulls : s.skipNulls
, d = "boolean" == typeof a.encode ? a.encode : s.encode
, h = "function" == typeof a.encoder ? a.encoder : s.encoder
, p = "function" == typeof a.sort ? a.sort : null
, v = void 0 !== a.allowDots && a.allowDots
, m = "function" == typeof a.serializeDate ? a.serializeDate : s.serializeDate
, g = "boolean" == typeof a.encodeValuesOnly ? a.encodeValuesOnly : s.encodeValuesOnly;
if (void 0 === a.format)
a.format = i.default;
else if (!Object.prototype.hasOwnProperty.call(i.formatters, a.format))
throw new TypeError("Unknown format option provided.");
var y, w, b = i.formatters[a.format];
"function" == typeof a.filter ? n = (w = a.filter)("", n) : Array.isArray(a.filter) && (y = w = a.filter);
var _, D = [];
if ("object" != typeof n || null === n)
return "";
_ = a.arrayFormat in o ? a.arrayFormat : "indices"in a ? a.indices ? "indices" : "repeat" : "indices";
var S = o[_];
y || (y = Object.keys(n)),
p && y.sort(p);
for (var M = 0; M < y.length; ++M) {
var x = y[M];
l && null === n[x] || (D = D.concat(u_(n[x], x, S, f, l, d ? h : null, w, p, v, m, b, g)))
}
var O = D.join(c)
, k = !0 === a.addQueryPrefix ? "?" : "";
return O.length > 0 ? k + O : ""
}
var _ = {
"json": "{\"id\":\"00914528435406\",\"jsonrpc\":\"2.0\",\"method\":\"auth.login\",\"params\":{\"sn\":\"wy12\",\"loginId\":\"手机号\",\"saltedPassword\":\"密码\",\"salt\":盐值,\"captchaKey\":\"3763286221\",\"captchaCode\":\"5864\",\"withAuth\":\"1\",\"withProfile\":\"1\",\"withBalance\":\"1\",\"terminal\":1,\"host\":\"mdfghg.5xpoijhtf.com\",\"fingerOSModel\":\"Chrome 117.0.0.0 | Windows 10\",\"ztsLang\":\"zh\"}}"
}
console.log(l_a_stringify(_))
Object(m.a)代码:
js
function object_m_a(t) {
var e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function n(t, e) {
return Math.floor(Math.random() * (e - t)) + t
}
var r = function(t) {
for (var r = Array(t), i = e.slice(0, 52), a = 0; a < r.length; a++)
r[a] = i[n(0, i.length)];
return r.join("")
}(24)
, i = function(t) {
var n, r, i, a, o, s, u, d = "", c = 0;
for (t = function(t) {
t = t.replace(/\r\n/g, "\n");
for (var e = "", n = 0; n < t.length; n++) {
var r = t.charCodeAt(n);
r < 128 ? e += String.fromCharCode(r) : r > 127 && r < 2048 ? (e += String.fromCharCode(r >> 6 | 192),
e += String.fromCharCode(63 & r | 128)) : (e += String.fromCharCode(r >> 12 | 224),
e += String.fromCharCode(r >> 6 & 63 | 128),
e += String.fromCharCode(63 & r | 128))
}
return e
}(t); c < t.length; )
a = (n = t.charCodeAt(c++)) >> 2,
o = (3 & n) << 4 | (r = t.charCodeAt(c++)) >> 4,
s = (15 & r) << 2 | (i = t.charCodeAt(c++)) >> 6,
u = 63 & i,
isNaN(r) ? s = u = 64 : isNaN(i) && (u = 64),
d = d + e.charAt(a) + e.charAt(o) + e.charAt(s) + e.charAt(u);
return d
}(t);
return "pwv|13|" + function(t, e) {
for (var n = "", r = 0, i = 0; i < e.length; i++) {
var a = t.charCodeAt(r % t.length)
, o = e.charCodeAt(i)
, s = o;
o >= 65 && o <= 90 && (a >= 65 && a <= 90 && (s = (a - 65 + (o - 65)) % 26 + 65),
a >= 97 && a <= 122 && (s = (a - 97 + (o - 65)) % 26 + 65),
r++),
o >= 97 && o <= 122 && (a >= 65 && a <= 90 && (s = (a - 65 + (o - 97)) % 26 + 97),
a >= 97 && a <= 122 && (s = (a - 97 + (o - 97)) % 26 + 97),
r++),
n += String.fromCharCode(s)
}
return n
}(r + "wxfEZdkAYYyBqbnMN", i) + "|" + r
}
总结
此网站内容还是比较简单,我这里分析的比较乱,自己分析的话可以参考一下。
另外,登陆的验证码可以使用python的ddddocr
,然后把整个流程串通起来就可以实现登陆了。