当前位置: 首页 > article >正文

Python实现WYY音乐下载

一、需求背景

WYY音乐作为国内主流音乐平台,其歌曲资源丰富但下载接口存在多重加密保护。本文将通过Python结合JS逆向技术,解析其核心加密逻辑,实现免费歌曲的下载功能。

二、技术难点分析

1. 接口加密机制

通过抓包分析可知,网易云核心接口使用两次加密:

  • 第一次:获取播放列表详情(/playlist/detail)

  • 第二次:获取歌曲下载地址(/song/enhance/player/url/v1)

2. 加密特征

请求参数包含两个关键字段:

params = 'wB86VLegW2dnyHI37+LxTZf4NrKoft+s6kROF0tcWs4LCQlrgaopaFZtak6x8TGsMPoLc1yXe8JEZP7CwGr5mA4/OoKXO/zUf9UYMyVuMMYRdLoKpMkWobbeLcwthG6kKBb5nDhxJOdDmvl+JS709WnXZYMbxZfXjKPgItjMujkjJYYT7LaG53f2mEFScsJI91gLV05T4DQlNRvpC6y6uHjwHBA/3LSrytaRinF7A40='
encSecKey = '71affe85fe12f4dd47ff873aa9c436fcf23ef1c2324020e3c268cdb33a03d7cab99377a066006861c9ca9e4e390d6a68c498415c5e77afd0cb6e6f077c793316587be7609873baab8935d68f1fa22c4287dcfb5b9b72062d1e11c9059b9d637b2820d9bd1c1265d13e8c4c86414a788b3db595c1fa3931a0fba02dbb9be93222'

三、逆向工程实现

1. 加密逻辑定位

通过浏览器开发者工具分析,定位到核心加密函数位于core_b7113131e0c3d9361b7b149f7ab7939f.js?b7113131e0c3d9361b7b149f7ab7939f.js中:

然后再根据参数关键词encSecKey在对应的js文件中搜索,进而分析通过js实现的方法

将所有涉及到的js文件中的function复制带自己电脑上的js文件中

完整js代码如下 后续可以将这份代码复制在本机命名为jm.js:

var data_01 = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
const CryptoJS = require('crypto-js');
var maxDigits, ZERO_ARRAY, bigZero, bigOne, dpl10, lr10, hexatrigesimalToChar, hexToChar, highBitMasks, lowBitMasks, biRadixBase = 2, biRadixBits = 16, bitsPerDigit = biRadixBits, biRadix = 65536, biHalfRadix = biRadix >>> 1, biRadixSquared = biRadix * biRadix, maxDigitVal = biRadix - 1, maxInteger = 9999999999999998;
setMaxDigits(20),
dpl10 = 15,
lr10 = biFromNumber(1e15),
hexatrigesimalToChar = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"),
hexToChar = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"),
highBitMasks = new Array(0,32768,49152,57344,61440,63488,64512,65024,65280,65408,65472,65504,65520,65528,65532,65534,65535),
lowBitMasks = new Array(0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535);


function RSAKeyPair(a, b, c) {
    this.e = biFromHex(a),
    this.d = biFromHex(b),
    this.m = biFromHex(c),
    this.chunkSize = 2 * biHighIndex(this.m),
    this.radix = 16,
    this.barrett = new BarrettMu(this.m)
}
function twoDigit(a) {
    return (10 > a ? "0" : "") + String(a)
}
function encryptedString(a, b) {
    for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e; )
        c[e] = b.charCodeAt(e),
        e++;
    for (; 0 != c.length % a.chunkSize; )
        c[e++] = 0;
    for (f = c.length,
    g = "",
    e = 0; f > e; e += a.chunkSize) {
        for (j = new BigInt,
        h = 0,
        i = e; i < e + a.chunkSize; ++h)
            j.digits[h] = c[i++],
            j.digits[h] += c[i++] << 8;
        k = a.barrett.powMod(j, a.e),
        l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix),
        g += l + " "
    }
    return g.substring(0, g.length - 1)
}
function decryptedString(a, b) {
    var e, f, g, h, c = b.split(" "), d = "";
    for (e = 0; e < c.length; ++e)
        for (h = 16 == a.radix ? biFromHex(c[e]) : biFromString(c[e], a.radix),
        g = a.barrett.powMod(h, a.d),
        f = 0; f <= biHighIndex(g); ++f)
            d += String.fromCharCode(255 & g.digits[f], g.digits[f] >> 8);
    return 0 == d.charCodeAt(d.length - 1) && (d = d.substring(0, d.length - 1)),
    d
}
function setMaxDigits(a) {
    maxDigits = a,
    ZERO_ARRAY = new Array(maxDigits);
    for (var b = 0; b < ZERO_ARRAY.length; b++)
        ZERO_ARRAY[b] = 0;
    bigZero = new BigInt,
    bigOne = new BigInt,
    bigOne.digits[0] = 1
}
function BigInt(a) {
    this.digits = "boolean" == typeof a && 1 == a ? null : ZERO_ARRAY.slice(0),
    this.isNeg = !1
}
function biFromDecimal(a) {
    for (var d, e, f, b = "-"

http://www.kler.cn/a/592923.html

相关文章:

  • Redis复制(replica)主从模式
  • 【CMake指南】第12篇:CMake Unity Build 详解
  • Leetcode Hot 100 79.单词搜索
  • 如何把master迁出的bug修改分支,合并、删除本地、删除远端
  • 前端小食堂 | Day17 - 前端安全の金钟罩
  • leetcode日记(100)填充每个节点的下一个右侧节点指针
  • Vue3中ts父子组件传值
  • CSGHub开源版本v1.5.0更新
  • Leetcode-100 回溯法-子集
  • 单元测试、系统测试、集成测试、回归测试的步骤、优点、缺点、注意点梳理说明
  • 【深度学习量化交易18】盘前盘后回调机制设计与实现——基于miniQMT的量化交易回测系统开发实记
  • Leetcode 刷题笔记1 单调栈part01
  • 瑞幸需要宇树科技
  • 使用hel-micro微服务实现在jsp项目中引入react组件
  • Jenkins自动化部署pigx项目的实践总结
  • DLMS电能表通讯协议学习笔记
  • 2025三掌柜赠书活动第八期:预训练语言模型:方法、实践与应用
  • 联核科技AGV无人叉车有哪些常见的安全防护措施?
  • Flutter小白零基础入门到高级项目实战全集
  • 解决uni-app授权弹框华为审核拒绝