Cytrogen 的个人博客

万圣节恶魔的领地

马上订阅 Cytrogen 的个人博客 RSS 更新: https://cytrogen.icu/atom.xml

JS 逆向网易云音乐

2023年11月28日 05:00

该文章记录了我如何逆向网易云 并制作一个简易的播放器(鸽了)

逆向网易云

用浏览器打开网易云的网站,随意挑选一首歌曲进行播放,同时检查网络选项卡中的响应。我们能看到媒体类型中有一个 .m4a 文件。直接用 Python 的 requests 爬取下来进行播放,够厚道,爬下来就能听。


当然在页面源代码里找这个 .m4a 文件是找不到的,不然也不会说要 逆向 网易云了。我们该如何找到这个 .m4a 文件的 URL 呢?继续看看网络选项卡里的请求:

赫然出现这么一个请求,返回的 JSON 数据中有 .m4a 的链接。嗯,就是你了!看看负载:

csrf_token 为空,重点是表单数据的 paramsencSecKey。其中的内容都是一大串反正不是明文的东西,那么逆向的目标就是找到这两个参数的生成方式。

原本想要直接在源代码里一个个找过去这两个参数,后来突然想到客户端反正都会朝 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token= 发送请求,那么直接在 XHR / 提取断点里选择所有包含着 v1?csrf_token= 的 URL 不就行了。

关注 arguments 的构造此时成为了我们的目标。

用调用堆栈陆续向上查看,发现 paramsencSecKey 依旧是加密过后的。哎,加把劲吧,继续向上查看。

一直到这一步…… 观察其前面的代码能发现一个非常有意思的事情:

  1. 变量 bKC1x 被赋值
  2. e1x.data 被赋值时,bKC1x 被用到了,参数中还赫然写着 paramsencSecKey
  3. 根据我们之前查看的调用堆栈,chF5K(X2x, e1x) 的第二个参数必定是 paramsencSecKey 的组合

这说明什么?说明 bKC1x 就是生成 paramsencSecKey 的关键!我们仔细分析一下它的构造:

var bKC1x = window.asrsea(JSON.stringify(i1x), bvh3x(["流泪", "强"]), bvh3x(Rf5k.md), bvh3x(["爱心", "女孩", "惊恐", "大笑"]));

其中第三个参数所使用的 Rf5k.md 的内容如下:

很想吐槽…… 这些字符串的意义是什么???

bKC1x 本身会生成一个字典,其中包含 encTextencSecKey 两个键。而屡次出现的 bvh3x() 函数的构造如下:

var bvh3x = function(chL5Q) {    var m1x = [];    j1x.bg2x(chL5Q, function(chK5P) {        m1x.push(Rf5k.emj[chK5P])    });    return m1x.join("")};

它的运作差不多是这样子的。

Rf5k.emj 是一个字典,构造非常激寒:

…… 谁来告诉我这些键到底都是什么意思???

也就是说 bvh3x() 函数接收参数,按照每个元素的字符串、对比 Rf5k.emj 字典中的键来返回对应的值,最后拼接成一个列表。

知道了 bKC1x 中后三个参数的生成方式,我们便只需要知道第一个参数 —— JSON.stringify(i1x) —— 是什么来头的了:

手到擒来,这个 id 不就是歌曲 id 么?!

参数已经全部知晓,最后要看网易云如何加密它们。window.asrsea() 函数作为加密这些参数的老大哥,它的构造如下:

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}

d() 函数需要好好说道说道。接收的四个参数我们已述说过,这里不废话了。d() 先创建了一个空字典 h,接着创建了一个 i。要知道 i 的值,我们需要知道 a() 的内容:

function a(a) {    var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";    for (d = 0; a >...

剩余内容已隐藏

查看完整文章以阅读更多