小工具知识网

当前位置: 首页 > 行业知识 > web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)

行业知识

web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)

2026-11-13 22:42:43 来源:互联网转载

web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)

一、webpack介绍:

​ Webpack 是一个模块打包工具,主要用于 JavaScript 应用程序。它可以将许多模块打包成一个或多个 bundle,从而优化加载速度和减少加载时间。Webpack 可以处理各种资源,包括 JavaScript、CSS、图片、字体等,并且可以将其转换为浏览器可以理解的格式。

Webpack 的主要特点包括:

  1. 模块化:Webpack 允许你将应用程序划分为许多小的、独立的模块,这些模块可以被重复使用,并且可以轻松地进行更改和更新。
  2. 高效性:Webpack 使用高级优化算法来最小化生成的 bundle 的大小,从而加快加载速度。它还支持代码拆分、懒加载等功能,以便进一步优化性能。
  3. 灵活性:Webpack 支持各种插件和加载器,可以用于处理不同类型的资源,并且可以扩展其功能以适应不同的项目需求。
  4. 可配置性:Webpack 提供了丰富的配置选项,可以根据项目需求进行灵活的配置,以满足不同的构建要求。

总的来说,Webpack 是一个强大的工具,可以帮助开发人员更高效地构建和维护 JavaScript 应用程序。它已经成为前端开发中不可或缺的一部分,被广泛使用于各种项目中。

二、webpack打包简介
1、webpack数组形式
!function(e) {    var t = {};    // 加载器  所有的模块都是从这个函数加载 执行    function n(r) {        if (t[r])            return t[r].exports;        var o = t[r] = {            i: r,            l: !1,            exports: {}        };        return e[r].call(o.exports, o, o.exports, n),            o.l = !0,            o.exports    }    n(0)}    ([        function () {            console.log('123456')        },              function () {            console.log('模块2')        },    ])
2、webpack对象形式
!function(e) {    var t = {};    //  所有的模块 都是从这个加载器 执行的  分发器    function n(r) {        if (t[r])            return t[r].exports;        var o = t[r] = {            i: r,            l: !1,            exports: {}        };        return e[r].call(o.exports, o, o.exports, n),        o.l = !0,        o.exports    }   n('xialuo')  // 对象 根据KEY 找模块}({        0: function () {            console.log('我是模块1  负责加密')        },        'xialuo': function () {            console.log('我是模块2  负责解密')        },        2: function () {            console.log('我是模块3  负责爬数据')        }    });
三、多个JS文件打包

​ 如果模块比较多,就会将模块打包成JS文件, 然后定义一个全局变量 window[“webpackJsonp”] = [ ],它的作用是存储需要动态导入的模块,然后重写 window[“webpackJsonp”] 数组的 push( ) 方法为 webpackJsonpCallback( ),也就是说 window[“webpackJsonp”].push( ) 其实执行的是 webpackJsonpCallback( ),window[“webpackJsonp”].push( )接收三个参数,第一个参数是模块的ID,第二个参数是 一个数组或者对象,里面定义大量的函数,第三个参数是要调用的函数(可选)

四、QQ音乐sign值获取
1、接口分析
// sign值生成// n方法为加载器o = n(147).default;i = o(e.data);sign = i;
2、扣取加载器方法
window = global;// 加载器!function(e) {    function t(t) {        for (var r, n, f = t[0], c = t[1], i = t[2], l = 0, u = []; l  
3、模块扣取(可以单个模块扣取,然后运行,缺什么补什么就可以了;也可以扣取整个js文件,然后通过require(‘./webpack.js’)形式引用即可)。这里为了方便采用了引用的方式。运行结果与网页对比,发现不一致情况。
这里出现这种情况,应该是有浏览器环境检测,我们没有补充。可以放到补环境框架中运行,然后补充对应所需环境;也可以手动补几个常见的浏览器环境(如:document、navigator、location等)并给手动补充的环境挂上代理。
// 挂代理代码(主要监听get、set方法)ld = {}; ld.config = {}; ld.config.proxy = true; // 增加属性,用于执行是否开启代理操作// 获取对象类型操作ld.typeObject = function typeObject(obj){    return Object.prototype.toString.call(obj);}// 代理函数ld.proxy = function proxy(obj, objName){    if(!ld.config.proxy){        return obj;    }    let handler = {        get:function(target, prop, receiver){            let result;            try{ // 防止报错                result = Reflect.get(target, prop, receiver); // 使用映射的方法,来调用get方法                // 获取对象类型                let type = ld.typeObject(result);                if(result instanceof Object){                    console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回类型:[${type}]}`);                    result = ld.proxy(result, `${objName}.${prop.toString()}`);                }else if(typeof result === "symbol"){                    console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${result.toString()}]}`);                }else{                    console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${result}]}`);                }            }catch(e){                console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 错误信息:[${e.message}]}`);            }                        return result        },        set:function(target, prop, value, receiver){            let result            try{ // 防止报错                result = Reflect.set(target, prop, value, receiver); // 使用映射的方法,来调用set方法                // 获取对象类型                let type = ld.typeObject(value);                if(value instanceof Object){                    console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回类型:[${type}]}`);                }else if(typeof value === "symbol"){                    console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${value.toString()}]}`);                }else{                    console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${value}]}`);                }            }catch(e){                console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 错误信息:[${e.message}]}`);            }                        return result        }};    return new Proxy(obj, handler);}
补齐缺少的属性值,结果就和浏览器一样了。
3、构造请求,获取所需数据
import requestsimport timeimport execjsheaders = {    'authority': 'u6.y.qq.com',    'accept': 'application/json',    'accept-language': 'zh-CN,zh;q=0.9',    'cache-control': 'no-cache',    'content-type': 'application/x-www-form-urlencoded',    'pragma': 'no-cache',    'referer': 'https://y.qq.com/',    'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',    'sec-ch-ua-mobile': '?0',    'sec-ch-ua-platform': '"Windows"',    'sec-fetch-dest': 'empty',    'sec-fetch-mode': 'cors',    'sec-fetch-site': 'same-site',    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',}data = '{"comm":{"cv":4747474,"ct":24,"format":"json","inCharset":"utf-8","outCharset":"utf-8","notice":0,"platform":"yqq.json","needNewCode":1,"uin":0,"g_tk_new_20200303":5381,"g_tk":5381},"req_1":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"5630580667","songmid":["001Xs1NW3wgWpq","0027Z2qE0pDuKY"],"songtype":[0,0],"uin":"0","loginflag":1,"platform":"20"}},"req_2":{"module":"music.musicasset.SongFavRead","method":"IsSongFanByMid","param":{"v_songMid":["0016aXcd24qSC8","001Xs1NW3wgWpq","0027Z2qE0pDuKY","003V4xd80ty2df"]}},"req_3":{"module":"music.musichallSong.PlayLyricInfo","method":"GetPlayLyricInfo","param":{"songMID":"0016aXcd24qSC8","songID":457240977}},"req_4":{"method":"GetCommentCount","module":"music.globalComment.GlobalCommentRead","param":{"request_list":[{"biz_type":1,"biz_id":"457240977","biz_sub_type":0}]}},"req_5":{"module":"music.musichallAlbum.AlbumInfoServer","method":"GetAlbumDetail","param":{"albumMid":"001ln9YB420a7b"}},"req_6":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"9307341590","songmid":["0016aXcd24qSC8"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20","filename":["RS020640pBtN0etKNM.mp3"]}}}'with open('./get_sign.js', 'r', encoding='utf-8') as f:    code_js = f.read()sign = execjs.compile(code_js).call('get_sign', data)params = {    '_': round(time.time() * 1000),    'sign': sign,}response = requests.post('https://u6.y.qq.com/cgi-bin/musics.fcg', params=params, headers=headers, data=data)print(response.json()["req_1"]['data']["midurlinfo"])
总结:
1、webpack打包的js文件,无论是单文件还是多文件,在逆向时首先需要找到对应的加载器。
2、加载器获取完成后,可以单个模块扣取代码并进调试,也可以扣取整个js文件,进行加载使用。
3、扣取完整代码后,出现结果与网页不一致时,大多数情况下是缺少浏览器环境;可以尝试补充一些常用的环境,并挂上代理方法查看缺少内容。
4、可以将扣取的完整代码,现在浏览器中运行,查看结果是否正确;在将代码在本地运行进行对比,可以快速确认是否是缺少环境导致结果不一样的。

上一篇:怎么删服务器帐号记录?

下一篇:源码编程器设置金币攻略,轻松掌握金币获取与设置技巧!