点击上方“蓝字”,关注更多精彩
本文将从0开始教你怎么解决某音乐的签名问题,实现爬取热评的功能,我们的目标是搞明白params和encSecKey的生成过程。(文中没有插入广告,请放心阅读)
首先搜索encSecKey。
可以看到这个参数在core文件中,然后我们转到Sources
直接搜索,有三个结果,第二和第三处可以看到这两个参数的取值,我们先定位第一处。
由上图可知,params由b方法得来,encSecKey由c方法得来,可以直接在这里下断点,也可以直接向上找,就在上面就有。
a、b、c、d方法都在上下文中。
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
function c(a, b, c) {
var d, e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d, a)
}
先抠出b、c方法,其实这里很清楚了,b是AES,c是RSA,然后我们下断点来看入参从哪来的。
function d(d, e, f, g) {
var h = {}
, i = a(16);
return h.encText = b(d, g),
h.encText = b(h.encText, i),
h.encSecKey = c(i, e, f),
h
}
首先我们看一下params,这个就是encText变量,这里可以看到,其实很简单,就是调了b方法即AES,入参两个,一个明文一个密钥,我们在下面下断点来调试。
这里放一下入参
d:{"rid":"R_SO_4_2102785224","threadId":"R_SO_4_2102785224","pageNo":"2","pageSize":"20","cursor":"1703117062380","offset":"0","orderType":"1","csrf_token":"9ad1ccb7e4ac0d59178520cd842b951d"}
e:010001
f:00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
g:0CoJUm6Qyw8W8jud
上面是d方法的入参,可以看到d实际是就是明文,e是RSA的公钥指数e,是公钥,g是AES的密钥。
这里可以看到encText进行了两次AES,第一次用的key是g,然后第二次是调用a方法。
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
由上文可知,a方法就是随机数,入参就是长度,这里的AES是调用了a方法获取16位随机数,然后用这个随机数把g作为密钥加密后的密文进行二次加密。
我们来验证一下
先把明文加密,这里的vi在上面的b方法中有,因为断点处已经调用了两次b方法,根据流程,我们用生成的随机数:xaCvZqDUWfbkAK0y(上图有)再把密文进行加密。
可以看到结果跟上面的断点处是一样的:VQUaeNYAiiO2v......
为了节省篇幅,这里的g参数就不赘述了,这个参数是不变的,一直是:0CoJUm6Qyw8W8jud,读者可以自行操作,会发现这个值不会变化。
那么这里我们已经解决了params参数,下面看encSecKey的生成过程。
根据上文已经知道encSecKey是调用的c方法,c(i,e,f)
i就是16位随机数,然后e是指数,f是公钥,所以我们只需要对这个随机数进行RSA加密,得到的密文就是encSecKey。
下面我们尝试一下
这里我引用了js实现RSA的库,对随机数进行加密,然后我们放开断点看看我们算的和网站的是否一致。
下面是我们算的
params:VQUaeNYAiiO2vBViJWoEA0DB61QPUagi1X+1jKmKGj8c51JMIP6QOzNoQuYyEBzF7n3D7y1pKscTrtC+I/XBJSyzUk4GtwqDvK/+GtBI8tSHMdvusxZldr0AYDoQa0OSVg2Z3RiGYq1BB1QYwC5w92euP0X+/GC/GzpswedjhcN2J2X7wh0eET7ZpBZqxuhDFFKVdfrsnnU+AgriW8oksegaHxVnXGSmAiTWn2qACQSK1CCZG7IfCc/z5JObFFqf2QZ96PdFkOhZrwSn5NiQjV2plHdCfXlJf67ocnohv/VLCzeIBtueO4jgGIOLkBWSLk0pUJCWBrXzPoaRb25jjj60IQ59KQs/OX/+n6dgS/U=
encSecKey:1601e9c737ce7b7d65ee42c1e391cb162a030c5abe5306bf1e52e35c10ea88663bb5839571a3b79b212ffbdc583f5381ccdbd1d384ad25ff0289651aa925e319fdaa892743c360f560eb9b1282b3bc2ca209f8006f0b62e911fc0ab8b8e838329360e661e4d4f8d3b1c2ac11c9ca44ff2cee50f054eb44a7a43b1714fb625a9c
看看网站请求的
可以看到是一样的,我们可以尝试重发一下请求。
成功获得数据。
既然是从0开始,那还要解决d参数的问题
{"rid":"R_SO_4_2102785224","threadId":"R_SO_4_2102785224","pageNo":"2","pageSize":"20","cursor":"1703117062380","offset":"0","orderType":"1","csrf_token":"9ad1ccb7e4ac0d59178520cd842b951d"}
这里面最主要的是rid、threadId、cursor,这里前两个是一样的,而第三个实际是一样就能看出来是时间戳。
那么我们看看rid怎么来的。
网址:https://music.***.com/#/song?id=2102785224
rid:R_SO_4_2102785224
很明显rid后面的数字就是songId,那么我们一样搜索R_S0_4_
其实还是在core文件里面,这里已经不需要再继续看了,其实已经定义了歌曲的前缀就是固定的。
上图是最终的效果,中间还有实现的过程,这个下次有空再说吧。
推荐阅读:QQ音乐Sign签名算法的VMP分析
https://wiki.shikangsi.com/post/3753/
查看本文请点击阅读原文。
附邀请码(3个):
e0fcf8dffbeb39a75f641d992414cf91
6a618666383cee7c00e9aabf108371e7
f13b56323a62140f64da97ab0614912b
有什么问题欢迎留言或私信,谢谢阅读。