对网易云评论 JS加密 进行破解爬取评论
2019-07-17 14:50 Xiao_Chen 阅读(1156) 评论(0) 编辑 收藏 举报爬过网易云评论的都知道,网易云的歌曲都是通过 <iframe> 便签进行层层迭代,而且数据都是异步加载的,就算是使用Selenium也要进行框架的转换,非常麻烦,且效率低下。
通过Chrome抓包得到评论的URL
可以看到评论的URL使用POST传进了两个参数,这一看就是加密过的,直接访问肯定是进不去的,猜测应该是JS加密,要破解只能去查看JS源码了。
在Initiator中可以看到 JS 目录的位置,在
格式化后放到本地,查找参数关键字以找到相关的JS代码,比如查找 “encSecKey”
运气不错一下就找到了,可以看到参数的值分别是bYc1x.encText,bYc1x.encSecKey,而bYc1x是由asrsea()方法传进4个参数构建的,再查找asrsea,
得到一长串混淆的JS代码,根本没法解析变量的意思,但是似乎找到了加密的方式 CryptoJS.mode.CBC。
要是想完全解密经过多层混淆的代码估计JS功底得非常深厚,所以这里取巧直接在本地输出参数看下参数的值,然后进行反加密。
这里我使用的是 Fiddler 去替换原来的JS代码,在控制台输出参数的值。因为服务器的资源是先放到浏览器上,浏览器再展示给我们,所以可以替换掉服务器的代码,输出参数的值。
打开 Fiddler,点击AutoResponser, 把Enable rules , Unmatched requests passthrough和 Enable Latency全部勾上。
然后刷新页面,在下方输入 Select Script
找到我们需要更改的JS源码,拖到右侧AutoResponser界面。
其中左边是你需要替换掉的JS文件,右边是你想要应用的文件路径。
我们想要输出未经加密的参数,所以在源码中添加
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