腾讯音乐sign参数逆向 评论点赞接口签名完整复现

在进行腾讯音乐sign参数逆向时,你有没有想过,一个看似普通的 sign 参数,背后竟然藏着一套复杂的加密逻辑?

在逆向腾讯音乐 API 的过程中,我顺着 sign 的生成逻辑一路追查,最终在一个叫 ie 的函数里发现了一个由 多个 case 分支组成的解释器结构。它维护着自己的操作数栈、程序计数器,逐条解析并执行指令——这根本不是普通的加密函数,而是一个独立的解释器引擎

这意味着一件事:如果想在本地复现签名逻辑,就必须把整个解释器结构完整抠出来

这篇文章记录了我从定位签名入口、分析解释器结构,到最终在 Node.js 中成功运行并生成一致签名的完整过程。如果你也曾在逆向中面对过类似的”黑盒”,希望这篇实战记录能给你一些启发。

腾讯音乐sign参数逆向 评论点赞接口签名完整复现
图1:评论点赞接口请求

一、抓包分析:锁定评论点赞接口

打开企鹅音乐进入评论区域,随便找个用户的评论点赞,接口请求路径为 /cgi-bin/musics.fcg。点击这个请求查看载荷选项卡,可以看到查询字符串参数中就包含了我们需要逆向的 sign 参数,长度为45位。

逆向
图2:载荷中的sign参数

二、全局搜索:定位sign赋值位置

刷新整个页面,使用 "sign:" 进行全局搜索,搜索的所有结果都指向 vendor.chunk.xxxx.js 文件。我们在该文件中的所有 "sign:" 位置都打上断点,然后再次点赞,看看触发的是哪一个断点。

腾讯音乐sign参数逆向 评论点赞接口签名完整复现
图3:全局搜索定位sign

三、断点调试:找到加密入口ie函数

继续在界面上找一条评论点一下赞,成功触发了断点,最终断点在 J 函数这里。可以看到加密参数 sign 是由 u 进行赋值的,继续往上看,看到一句 u = ie(r.data)

r.url = J({
    encoding: "ag-1",
    sign: u
}, r.url),
腾讯音乐sign参数逆向 评论点赞接口签名完整复现
图4:断点触发,找到ie函数

在开发者控制台执行一下 ie(r.data)ie 函数能正常生成 sign 的值,其中 r.data 是一大段很长的字符串,用来生成 sign 的参数。

ie(r.data)
'zzc4981cddixsjg7druwbseaoo9ymtzz4gca56df60'
r.data
'hd5PqA4rZ9EmQnyYQBhrHm9nEpEEyGvDzsGyVkGv8lNMAJmDNOOS05V/Q8RpkZHWm3TinXwZA/V+J+QozsHWaTd6tWCwPCl+1E7adBg7wMZ9f6HEDrLYk3krAq6oqJ3PQkCWhQpNx1fZLJ9SQUdEfUsP0VR/mKMKx+IBLAdCumDafwolnkPXoioE9asve+P+l8W2T/isM0cxIcBABezpQOPJ/KSoa1ymxnArXWCx9tFOi2Rf3JMZ2agQ8FmBJclG1xOd/bqPT/9xwoRTcRaIkiwhLwjvfwYYXNmCAQBv5ojciyZJeS17SNvnim+9UOrw6fCyEW1OSfTOZmRdfMt49isoNF/fBsOxyaenb9I7JeAqGJ5Kv7uMowgjUT/d0g57shyj9O7FG4YVjU9WePsggM1MfWV9pxUbScnZ7zvSWsImwkFIf3L+RLrHIYBBC2UNuKDcegFILvJibPfWKl0YCkoNn+RH2F9gF1vHB7fJsoAMhx4/jOHMiaiXT2uI/loQzBnlh/WjEzHcVtpHscQyIb//t2rjOTxPZ34qN0o9bpwELIGFg7FMjRt7V4ZTcxWtyQOTbOY2LoRWen8fziG/NnSjHhBBDTAQL0k='
腾讯音乐sign参数逆向 评论点赞接口签名完整复现
图5:控制台执行ie(r.data)生成sign

四、算法分析:解释器结构

既然确定了是在 ie 中生成的,那么我们直接跟进 ie 看一下它的结构。

(function() {
    return function(e, t) {
        var n = o(e)
          , i = function(e, t, o, s, u) {
            return function c() {
                // 目标函数内部省略.......
            }
        }
    }
})()("Xh7BFMoBogEUzAEU0gEU3AFGFMoBn........")

var ie = ne._getSecuritySign;

可以看到,ie 实际上是通过 ne._getSecuritySign 赋值的,而这个函数本质上是经过多层闭包嵌套后返回的 c 函数。

进一步分析 c 函数内部,你会发现一个由多个 case 分支组成的 switch 结构——它维护着自己的操作数栈程序计数器,逐条解析并执行指令。这已经不是普通的加密函数,而是一个独立的解释器引擎

五、代码扣取:完整抠出解释器并补环境

因此,我们只需要将 c 函数所在的整个闭包结构完整抠出,并在本地补全其依赖环境,即可在 Node.js 中独立执行该解释器,从而生成与浏览器一致的签名结果。

接下来新建一个 sign.js 文件,将上述自执行函数及其前面的 nere 定义一并拷贝下来。由于原代码运行在浏览器环境中,涉及 window 等全局对象,我们只需在文件最前面补充一句 window = global;,将 Node.js 的全局对象映射为浏览器环境的 window,即可确保后续代码正常执行。

window = global;

var ne = "undefined" !== typeof e ? e : "undefined" !== typeof window ? window : "undefined" !== typeof self ? self : void 0
    , re = function (e) {
        return e && "undefined" != typeof Symbol && e.constructor === Symbol ? "symbol" : typeof e
    };

// 此处粘贴自执行函数及其内部 c 函数完整结构...

六、本地验证:Node.js成功生成45位sign

一切准备就绪后,在文件末尾添加调用测试代码,验证签名生成是否正常:

var data = 'Zednxxxxx......';
var u = ie(data);
console.log('sign值:' + u);
console.log('sign长度:' + u.length);

运行 node sign.js,即可看到生成的签名值及其长度,与浏览器环境下的输出进行对比验证。

企鹅音乐sign参数逆向运行结果
图6:Node.js运行结果

从运行结果来看,生成的 sign 长度为45位,与我们抓包获取的接口签名长度完全一致。将生成的签名值与接口请求中的签名进行对比,也能完全匹配,说明我们成功复现了该签名生成逻辑。

七、技术总结

  • 定位方式:通过全局搜索 "sign:" 快速定位加密参数赋值位置
  • 加密入口ie(r.data) → ne._getSecuritySign → 闭包嵌套 → c 函数(解释器引擎)
  • 扣取方式:完整拷贝自执行函数及 nere 定义,补全 window = global 环境
  • 验证结果:Node.js 生成的 sign 长度为45位,与浏览器环境完全一致

至此,整个企鹅音乐sign参数逆向工作已全部完成,我们也成功完成了签名算法还原的全部流程。

温馨提示:本文技术仅供学习研究,请遵守相关法律法规,不得用于非法用途。

给TA打赏
共{{data.count}}人
人已打赏
技术文档

TikTok 逆向教程:拆解高风控 X-Gnarly 加密参数 油猴 Hook 定位签名入口

2026-6-25 1:40:31

WordPress教程技术文档

WordPress免插件去除腾讯视频广告

2020-9-23 21:05:34

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
有新私信 私信列表
搜索