Netease cloud climbed comments all know, NetEase cloud of the songs are performed by the <iframe> notes layers of iterations, and the data is loaded asynchronously, even using Selenium framework should be converted, cumbersome and inefficient .
Ethereal been reviewed by Chrome URL
You can see comments URL using the POST pass into two parameters, the look is encrypted, direct access to certainly get in, guess should be encrypted JS, JS to break only to see the source code.
In the Initiator can see where JS directory in
After formatting into the local look argument keywords to find relevant JS code, such as finding "encSecKey"
Lucky to find it, you can see the values of the parameters are bYc1x.encText, bYc1x.encSecKey, and bYc1x by asrsea () method pass in four parameters to build, and then find asrsea,
JS code to obtain a long list of confusing, simply can not resolve the variable meaning, but seems to have found a way to encrypt CryptoJS.mode.CBC.
If want to decrypt the code completely confused multilayer estimated JS knowledge was very deep, so here tricks look directly at the local values of the parameters output parameters, and then the anti-encryption.
I'm using here is to replace the original Fiddler JS code, the value of the output parameter in the console. Because the resource server is first placed on the browser, the browser and then show it to us, so you can replace the code server, the value of output parameters.
Open Fiddler, click AutoResponser, the Enable rules, Unmatched requests passthrough and Enable Latency all on the hook.
Then refresh the page, below the input Select Script
JS We need to find the source of change, drag the right side of AutoResponser interface.
Which left is that you need to replace the JS file, the right is the path to the file you want to apply.
We want to output unencrypted parameters, add in the source code
console.log(i3x);console.log(bkY2x(["流泪", "强"]));console.log(bkY2x(VM8E.md));console.log(bkY2x(["爱心", "女孩", "惊恐", "大笑"]));
PS:我是在没有格式化JS代码的时候就要添加了,格式化后会报错变量未定义什么的,所以是直接在源码适当的地方直接插入。报错的可以试着换个位置插入。
然后在AutoResponse中点击 save ,刷新网易云的页面,点击控制台,会看到:
多次输出检验可以后3个参数是定值,而第一个参数就包含了歌曲信息:
rid:就是歌曲的 id信息。
offset:用作评论的分页,比如offset=100,就是从第101条评论开始。
limit:限制的评论数,上限为100,超过会变成20,限制输出的评论数。
其他参数暂时还没有发现其用处。
部分源码分析:提取的源码如下:
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 } 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) } 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 } function e(a, b, d, e) { var f = {}; return f.encText = c(a + e, b, d), f } window.asrsea = d,
函数 asrsea() 传进了4个参数,然后asrsea 调用了 函数 a() ,阅读a()的代码,可以知道返回的是一个长度为 16 的随机字符串。那么我们可以给它一个定值。
再看对象 h,易知 h.encSecKey = c(i, e, f)是一个定值,最后就是带有歌曲参数的属性 h.encText,这个属性是通过两次加密后得到的。
研究加密算法后,知道 “0102030405060708” 是 vi偏移量,加密模式是 CryptoJS.mode.CBC。
然后回到反加密的过程,这里使用python编写解密过程。参考了网上的教程和该加密算法的加解密过程,代码如下:
PS:需要 Crypto 包
from Crypto.Cipher import AES import base64 import json # limit里面可以得到更多的评论,rid后加歌曲id # 下面参数通过控制台可以得到大部分,都是定值 # offset可以 first_param = '{rid: "R_SO_4_167844", offset: "120", total: "false", limit: "100", csrf_token: ""}' second_param = '010001' third_param = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' fourth_param = '0CoJUm6Qyw8W8jud' def get_params(): #根据该加密算法做出解密 iv = '0102030405060708' first_key = fourth_param second_key = 16 * 'F' h_encText = AES_encrypt(first_param, first_key, iv) h_encText = AES_encrypt(h_encText, second_key, iv) return h_encText def get_encSeckey(): #这个也是定值 encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c" return encSecKey def AES_encrypt(text, key, iv): if type(text) == type(b'123'): #这是判断当前变量的类型是bytes还是字符串,因为pycryptodome要 #求参数要是字节类型 text = text.decode('utf-8') pad = 16 - len(text) % 16 text = text + pad*chr(pad) iv = iv.encode('utf-8') key = key.encode('utf-8') encryptor = AES.new(key, AES.MODE_CBC, iv) text = text.encode('utf-8') encrypt_text = encryptor.encrypt(text) encrypt_text = base64.b64encode(encrypt_text) return encrypt_text if __name__ == '__main__': params = get_params() encSecKey = get_encSeckey() print(params.decode('utf-8')) print(encSecKey)
参考文章:
知乎:https://www.zhihu.com/question/36081767/answer/386606315
csdn:https://blog.csdn.net/weixin_40444270/article/details/81260638