【Python爬虫---js逆向】Js逆向之网易云音乐

通过逆向找打这个加密window.asrsea这个函数了

 

首先明确这里的4个参数分别对应什么,分别对应着下面四个参数

JSON.stringify(i8a), bsF6z(["流泪", "强"]), bsF6z(St0x.md), bsF6z(["爱心", "女孩", "惊恐", "大笑"]

所以发现JSON.stringify (i8a)被b函数加工以后,再次被b函数进行加工,接下来到b函数里面看看是什么

 终于发现了这是AES加密的特征

1,扣代码,对数据进行加密

接下来就是如何破解

第一种方法:直接全扣下来,缺什么就补什么

不知道如何加密的情况下,直接扣代码,缺什么就补什么(比较耗时,考验耐心,也比较好用)

打开pycharm,新建一个js文件

(注意了,你得安装好Node环境,pycharm写的js代码需要Node环境才能运行,而且浏览器环境跟Node环境有一些区别,我们从浏览器环境扣下来的js代码,在node环境运行的话会有些问题,根据具体问题补环境即可,比如说Node下js不能操作dom,没有window对象,如果扣下来的代码有window对象或者右操作dom的代码则需要进行适当的补环境)

所以自行百度准备好node环境

接下来可以扣代码了,思路就是缺什么函数,从浏览器复制什么函数,直到补完位置

比如说,就从加密入口函数下手

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
}
    var first = '{"logs":"[{\\"action\\":\\"mobile_monitor\\",\\"json\\":{\\"meta._ver\\":2,\\"meta._dataName\\":\\"pip_lyric_monitor\\",\\"action\\":\\"render\\",\\"userAgent\\":\\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36\\",\\"chromeVersion\\":116,\\"resourceId\\":1974443814,\\"resourceType\\":\\"song\\"}}]","csrf_token":""}'

    var second = '010001'
    var third = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
    var forth = '0CoJUm6Qyw8W8jud'
    var result = d(first,second,third,forth)
console.log(result)

加密函数是d,d需要四个参数,之前讲过了,分别是

JSON.stringify(i8a), bsF6z(["流泪", "强"]), bsF6z(St0x.md), bsF6z(["爱心", "女孩", "惊恐", "大笑"]

分别在console里面输出一下可以拿到一个他的值(而且不是随机的,是固定的)

需要注意的是第一个参数,JSON.stringify这个函数 用于把一个对象序列化,简单理解就是变成字符串,如有个对象{"name":"aini","age":18},序列化以后就成了'{"name":"aini","age":18}',整体用单引号包裹,变成了字符串(可以自己百度一下JS序列化反序列相关知识

接下来就是执行函数。缺什么补什么,直到成功为止

(注意运行js代码需要Node环境,请提前下载安装好,还有就是在终端cd 到你当前目录再运行)

 

b函数没找到,缺什么就补什么

 

就这样缺什么就补什么,通过九九八十一难,终于所有加密代码都扣完了、

注意:有些需要补的函数直接全局搜即可,找起来比较快,比如现在提示缺digitToHex函数,那直接复制去浏览区全局搜,步骤如下

 

 就这样很容易的找到函数了

第二中方法,用第三方库扣代码

首先我们需要安装第三方库 crypto-js

可以用包管理软件npm ,如果你下载安装好了node环境而且配置好了环境变量npm可以直接使用的

先检车是否有npm 

打开终端以后 输入 npm -v 如果看到版本说明安装好了,如果报错请百度一下,如何安装node和npm

npm install crypto-js 提示升级一下npm版本,那就先进行升级

 我之前安装过这个包,所以我不安装了,我直接给大伙上代码

首先需要引入我们安装的crypto-js包

node环境中用 requere函数

还有从一个Rsa加密文件里分别取出三个函数(这个文件内容很长,就不放这里了,有需要的留言)

我们注意带!function里面是一个立即执行函数,里面还有a,b,c,d四个函数,只要我们进行适当替换,就可以不用扣第一种方法一样扣大量代码了

const CryptoJS = require("crypto-js")
var window = this

const {
	setMaxDigits,
	RSAKeyPair,
	encryptedString
} = require("./Ras加密");
!function() {
    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,
    window.ecnonasr = e
}();

    var params = {
        csrf_token: "",
        encodeType: "aac",
        ids: "[1325905146]",
        level: "standard"
    }
    var second = '010001'
    var third = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
    var forth = '0CoJUm6Qyw8W8jud'


function fn(params) {
       return window.asrsea(JSON.stringify(params),second,third,forth)
}


function c(a,b,c){
    var d,e;
    return setMaxDigits(131),
        d = new RSAKeyPair(b,"",c),
        e = encryptedString(d,a)
}


这是一个立即执行函数,里面是a,b,c,d四个函数,主要加密逻辑就在其中,我们已经导入了crypto-js包,还有从RSA加密里面导入了三个函数这个解密文件就写完了

需要注意的是var windows = this 

因为我们扣的代码里有window,而node里没有window ,所以需要补window环境 

2,接下来就是用Python写代码进项爬取音乐

import requests

import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')

import execjs
url = 'https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='

f = open('用第三方库扣代码.js',mode='r',encoding="utf-8")
js_code = f.read()


params = {
	'csrf_token': "",
	'encodeType': "aac",
	'ids': "[1325905146,2025152494]",
	'level': "standard"
}

js = execjs.compile(js_code)
res = js.call("fn",params)


data = {
'params': res['encText'],
'encSecKey': res['encSecKey']
}
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}
session = requests.Session()
session.headers = headers

res = session.post(url=url,data=data)
dic = res.json()

items = dic['data']

for i in items:
	print(i['url'])

 这是Python代码,我们直接读取第三方库扣代码文件里的代码,执行,拿到加密结果以后既可以发请求,获取到URL音乐URL了

 接下来就是再往这个URL发请求,直接拿到相应结果以后,以二进制形式写入到文件就可以了

由于能分享的内容有限,详细逆向过程被迫删掉了,想了解的可以技术交流一下

好了今天就讲到这里,如果遇到问题,或者不懂的地方可以留言,我会及时回复的