Echo Music 反爬技术全揭秘:签名混淆破解与PoToken JS求解器深度解析
【免费下载链接】Echo-MusicA modern Android music app with ad-free streaming, synced lyrics, offline playback, and an intuitive user experience.项目地址: https://gitcode.com/gh_mirrors/ec/Echo-Music
你是否好奇免广告音乐流媒体 App 是如何绕开 YouTube 的层层防护的?Echo Music 是一款现代 Android 音乐应用,提供免广告播放、同步歌词、离线下载与直觉式体验。它的流媒体引擎藏着两套硬核技术:一套签名混淆破解(cipher deobfuscation)流水线,负责还原被混淆的播放地址;一套基于PoToken JavaScript 求解器的完整性令牌生成器,负责通过 YouTube 的 BotGuard 校验。本文用尽量直白的方式,带你拆解这套「反爬幕后技术」的完整设计。
🔍 为什么 YouTube 流媒体链接会「加密」?
当普通浏览器打开一个 YouTube 音乐页面时,API 返回的流媒体地址其实是一个「半成品」:
- 签名混淆(signature cipher):URL 里带着
s(被搅乱的假签名)和sp(签名参数名)等参数,只有执行了一段高度混淆的 JavaScript 后,才能把假签名还原成真签名。 - n 参数变换:URL 中的
n值必须经过一段同样混淆过的函数变换后,地址才有效。 - PoToken 完整性令牌:Web 客户端还需要携带一个由 BotGuard 协议生成的令牌(
pot参数),用来证明「请求来自真实浏览器环境」,这是近年反爬的核心手段。
Echo Music 的解法不是逆向出固定公式(公式随播放器版本频繁轮换),而是在手机上复刻一个安全的 JavaScript 执行环境,让 YouTube 自己的混淆代码在 App 内部运行并给出结果。相关代码集中在三个模块:
| 模块 | 职责 | 源码位置 |
|---|---|---|
| 签名去混淆 | 还原s签名、变换n参数 | utils/cipher/ |
| PoToken 求解器 | 运行 BotGuard、铸造完整性令牌 | utils/potoken/ |
| JS 求解内核 | AST 解析与求解器脚本 | assets/solver/ |
🧩 签名破解流水线:从混淆 JS 到可播放 URL
核心入口是 CipherDeobfuscator.kt,整体流程可以概括为「定位 → 查表 → 执行」三步:
- 定位播放器版本:FunctionNameExtractor.kt 先用正则从巨大的 player JS 里提取 8 位十六进制的「player hash」——相当于播放器的版本号。
- 查配置表:用 hash 查询 PlayerConfigStore.kt 维护的配置表,直接拿到签名函数名(如
Tl(48,5831,INPUT)这类描述)和 n 变换类名,数据来自内置资源 player_configs.json 并叠加远程更新,播放器轮换时无需发新版 App 即可修复。 - 执行还原:若查表未命中,FunctionNameExtractor.kt 会退回到一组签名函数正则模式现场提取;随后 CipherWebView.kt 在独立 WebView 中加载 player JS,调用真实函数把
s还原为真签名拼回 URL。n参数变换(transformNParamInUrl)也在同一个 WebView 内完成。
🧠 PoToken JS 求解器:在 WebView 里「铸造」令牌
PoToken(Proof-of-Work Token)不能凭空伪造,必须在类浏览器环境里跑完 BotGuard 协议。PoTokenWebView.kt 完整复刻了这一过程:
- 加载本地
po_token.html,在页面中注入 BotGuard 脚本; - 通过
jnn/v1/Create接口拿到挑战数据,在 JS 侧运行runBotGuard得到信号输出; - 再调
jnn/v1/GenerateIT换取integrityToken,随后createPoTokenMinter建好「铸币器」; - 每次播放时,只需把视频 ID 交给
obtainPoToken,即可快速铸出一枚 token(PoTokenWebView.kt)。
工程上还有不少细节让它稳定可用:
- Kotlin ↔ JS 桥接:通过
@JavascriptInterface双向通信,JS 结果以 Base64 传回,异常则携带完整堆栈上报; - 会话复用:PoTokenGenerator.kt 用互斥锁保证 WebView 单例,streaming pot 按 sessionId 缓存、player pot 按视频铸造,过期(提前 10 分钟判定)自动重建;
- 失败兜底:单次铸造失败会强制重建 WebView 重试一次;渲染进程崩溃(
onRenderProcessGone)则标记 WebView 死亡并整体换新的。
📜 JS 求解器三件套:把逆向做成可测试的资产
assets/solver/ 目录下的三个脚本是纯 JavaScript 方案的核心,服务于 EjsNTransformSolver.kt 处理的 SABR(自适应音频流)n 参数变换:
- meriyah.js:高性能 JS 解析器,把数百 KB 的混淆代码解析成 AST 语法树;
- astring.js:AST 序列化器,可把改写的语法树重新输出为代码;
- yt.solver.core.js:求解内核(由 yt-dlp 的 ejs 项目自动生成),内置一组AST 结构匹配模式——不是脆弱的字符串正则,而是匹配「变量声明里调用 decodeURIComponent」这类结构特征,能稳定从混淆代码中定位 n 变换函数。
AST 匹配比正则更抗混淆变化:变量名怎么改都不影响结构判定,这也是此类破解方案长期保持可用的关键。
🚀 最终拼装:一条可播放的流媒体 URL
YTPlayerUtils.kt 把上述能力串成完整播放链路:请求 player API → 签名去混淆 → n 参数变换(SABR 走 ejs 求解器)→ 追加pot令牌;多个 InnerTube 客户端之间自动回退,PoToken 按需惰性生成。
🛡️ 自愈设计:配置热更新与故障退避
这套系统面对的是持续演变的对手,因此可靠性设计是重头戏:
- 三级配置源:内置资源兜底 → 远程 JSON 热更新(带 ETag 协商,6 小时 TTL)→ 磁盘缓存,见 PlayerConfigStore.kt;
- 拒绝即刷新:流地址被服务端拒绝时(onStreamRejected)自动拉取新配置;
- 退避策略:RendererRecoveryPolicy.kt 在 WebView 连续崩溃时进入退避窗口,避免恶性循环;配置表 epoch 一变,WebView 自动重建。
总结
Echo Music 的反爬方案可以浓缩为一句话:不猜公式,跑真代码。签名破解靠「查表 + 现场提取 + WebView 执行」,PoToken 靠本地 BotGuard 求解器,而 AST 级 JS 求解内核与可热更新的配置表让整个系统具备了持续对抗 YouTube 反爬升级的能力——这正是开源社区能把「免广告流媒体」体验做稳的底层原因。
【免费下载链接】Echo-MusicA modern Android music app with ad-free streaming, synced lyrics, offline playback, and an intuitive user experience.项目地址: https://gitcode.com/gh_mirrors/ec/Echo-Music
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考