某音乐逆向

概要

本篇文章主要介绍了某音乐平台播放页面的js逆向思路。

抓包分析

选取一首歌曲,进入到播放页面,打开浏览器的开发者模式,点击播放按钮,进入到XHR选项,可以看到有一个https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=链接,响应值中包含了本首歌曲的链接,将歌曲链接放到浏览器中打开,可以直接播放。
播放页面截图
查看请求链接的请求头和请求的表单数据,未发现请求头中包含有加密字段,而在请求的表单数据中有两个加密参数paramsencSecKey,下面将对这两个参数进行分析。
在这里插入图片描述

逆向分析

我们先搜索加密参数,这里搜索的是encSecKey,发现有多个结果,挨个查看搜索结果,在第一个搜索结果中就找到了参数位置
参数位置
在参数位置打上断点,再次点击播放按钮,js在断点处断开,说明参数生成的位置是正确的,在参数上方展示有本次请求的url(表单数据生成方式相同),若url与歌曲生成的url(https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=)不同,则继续执行,直到链接相同。
断点调试
查看bVc8U的值,发现包含了我们想要的结果,而这个参数就在上一行生成

var bVc8U = window.asrsea(JSON.stringify(i3x), bsF5K(["流泪", "强"]), bsF5K(St0x.md), bsF5K(["爱心", "女孩", "惊恐", "大笑"]));
e3x.data = j3x.cr4v({
    params: bVc8U.encText,
    encSecKey: bVc8U.encSecKey
})

查看window.asrsea方法,跳转到了d方法,此方法有四个参数,分别对应了window.asrsea的四个参数,在控制台中打印这四个值,经过多次测试,发现后三个参数为固定值,而第一个参数是一个json字符串,其内的ids为当前页面的歌曲id:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
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
}
const one = '{"ids":"[2077531015]","level":"standard","encodeType":"aac","csrf_token":""}'
const two = '010001'
const three = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
const four = '0CoJUm6Qyw8W8jud'

console.log(d(one, two, three, four))

在浏览器中a方法打断点,进入到此方法中,将a方法复制出来,将后续的bc方法都复制出来

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)
}

从上边代码可以看出b方法使用了CryptoJS加密库,于是我们先引入此库(需要nodejs环境且安装了这个库)

var CryptoJS = require('crypto-js')

再次运行报错
在这里插入图片描述
setMaxDigits打上断点,进入到setMaxDigits函数内部,发现这部分为RSA加解密的函数,将有关函数全部复制出来,再次运行,即可得到加密的参数
在这里插入图片描述
在这里插入图片描述

结果

以赵雷的成都为例,歌曲的播放页链接为https://music.163.com/#/song?id=436514312,因此歌曲的id为436514312,那么就可以下载本首歌曲
在js中定义一个方法用来调用:

function key(music_id) {

    // music_id: 歌曲id, 字符串
    var second = '010001'
    var third = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
    var forth = '0CoJUm6Qyw8W8jud'
    var json_str = JSON.stringify({"ids": `[${music_id}]`, "level": "standard", "encodeType": "aac", "csrf_token": ""})
    console.log(d(json_str, second, third, forth))
    return d(json_str, second, third, forth)
}

使用python代码调用:

import requests
import execjs

from utils import Tool


def main():
    # 音乐id, 成都-赵雷
    music_id = '436514312'

    # 音乐接口url
    url = 'https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='
    with open('./js_data.js', 'r', encoding='utf-8') as f:
        js = execjs.compile(f.read())

    # 调用js加密
    js_data = js.call('key', music_id)
    data = {
        'params': js_data['encText'],
        'encSecKey': js_data['encSecKey']
    }

    # 请求音乐接口
    response = requests.post(url, data=data, headers=Tool().headers)
    print(response.json())
    m4a_url = response.json()['data'][0]['url']
    resp = requests.get(m4a_url, headers=Tool().headers)
    with open('./成都-赵雷.mp3', 'wb') as mf:
        mf.write(resp.content)


if __name__ == '__main__':
    main()

代码运行后,就可将此歌曲下载到本地

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值