MyFreeMP3致力于免费音乐下载,打开之后就能看到很多当下比较热门的音乐,并且页面内没有任何广告,2022年发布过一篇文章,讲解了MyfreeMP3搜索接口参数逆向,最近看了看这个网站搜索接口的参数已经修改,直接开始分析新版本token参数如何生成。
进入网站打开调试工具,随意搜索一首歌可以抓到Search包,该包提交的表单中有一个token参数为加密值,直接跟栈分析,最后能够定位到参数生成位置在下图此处
此处的代码可以修改修改,更能直观的看出加密流程,其中的a是一个长度为135的数组,先经过了qs函数获得一串长度为180的字符串,然后再经过crypto.md5方法生成wordArray对象。
function encrypt_token(e) {
const t = "yGz4n9XE9xYy2Oj5Ub7E6u9a5p5aIWZYe53Orq5wE5UgnjbWq0410WTvmLBO1Z2N";
const a = qs(t.toString(), e.toString());
return "20230327." + cryptoJS.MD5(Bs(a));
}
qs函数和Bs函数大家自行跟栈分析,文章中直接将这部分函数的代码贴出,供大家自行学习
function Bs(e) {
var s, o, i, a, l, r, c, u, f = 0, h = "", m = {
UvJUa: "0|6|2|4|7|5|1|8|3"
};
do {
for (var y = m["UvJUa"].split("|"), g = 0; ; ) {
switch (y[g++]) {
case "0":
s = e[f++];
continue;
case "1":
r = 63 & u >> 6;
continue;
case "2":
i = e[f++];
continue;
case "3":
h += Es["charAt"](a) + Es["charAt"](l) + Es["charAt"](r) + Es["charAt"](c);
continue;
case "4":
u = ((s << 16) | (o << 8)) | i;
continue;
case "5":
l = u >> 12 & 63;
continue;
case "6":
o = e[f++];
continue;
case "7":
a = u >> 18 & 63;
continue;
case "8":
c = u & 63;
continue
}
break
}
} while (f < e.length);
var v = e.length % 3;
return h + "===".slice(v || 3);
}
function Fs(e, t) {
return e.charCodeAt(Math.floor(t % e.length));
}
function qs(e, t) {
const a = t.split("");
return a.map(function(t, a) {
return t.charCodeAt(0) ^ Fs(e, a + 1 - 1)
})
}
Bs函数中还调用了Es参数,直接搜索Es,可以找到Es是固定死的值,拿出来直接var Es = xxx即可。
最后所有的代码如下
const cryptoJS = require("crypto-js")
var Es = "pW8jg/mke6cO1F4CTuaiswhZfQGzMyq5NJRLPVIvDxlA7=E3YrSUoH0b2BXKn9td+";
function Bs(e) {
var s, o, i, a, l, r, c, u, f = 0, h = "", m = {
UvJUa: "0|6|2|4|7|5|1|8|3"
};
do {
for (var y = m["UvJUa"].split("|"), g = 0; ; ) {
switch (y[g++]) {
case "0":
s = e[f++];
continue;
case "1":
r = 63 & u >> 6;
continue;
case "2":
i = e[f++];
continue;
case "3":
h += Es["charAt"](a) + Es["charAt"](l) + Es["charAt"](r) + Es["charAt"](c);
continue;
case "4":
u = ((s << 16) | (o << 8)) | i;
continue;
case "5":
l = u >> 12 & 63;
continue;
case "6":
o = e[f++];
continue;
case "7":
a = u >> 18 & 63;
continue;
case "8":
c = u & 63;
continue
}
break
}
} while (f < e.length);
var v = e.length % 3;
return h + "===".slice(v || 3);
}
function Fs(e, t) {
return e.charCodeAt(Math.floor(t % e.length));
}
function qs(e, t) {
const a = t.split("");
return a.map(function(t, a) {
return t.charCodeAt(0) ^ Fs(e, a + 1 - 1)
})
}
function encrypt_token(e) {
const t = "yGz4n9XE9xYy2Oj5Ub7E6u9a5p5aIWZYe53Orq5wE5UgnjbWq0410WTvmLBO1Z2N";
const a = qs(t.toString(), e.toString());
return "20230327." + cryptoJS.MD5(Bs(a));
}
console.log(encrypt_token(
encodeURIComponent(JSON.stringify(
{
type: "YQM",
text: "泡沫",
page: 1,
v: "beta",
_t: 1706099652039
}
))
))
将表单中的_t和text参数修改成与浏览器一致进行测试,测试结果如下,生成参数一致,新版本的参数自己动手跟一跟其实还是挺简单的,加油