微信视频号视频加密逆向分析与解密方案
在数字化内容传播时代,视频平台为了保护版权内容,通常会对视频进行加密处理。本文将深入分析微信视频号的视频加密机制,通过逆向工程技术揭示其加密原理,并提供可行的解密方案。这不仅是一次技术探索,更是对现代网络安全和逆向工程领域发展趋势的观察。
🎯 项目背景
在日常使用微信视频号时,我们可能会遇到需要保存重要视频的场景,比如:
- 📚 学习资料保存:保存有价值的教程视频
- 📰 资讯内容备份:保存重要的新闻资讯视频
- 🎨 创作素材收集:收集优秀的创意视频作为参考
- 📖 个人收藏整理:整理个人喜爱的视频内容
然而,微信视频号为了保护内容版权,对视频进行了加密处理,导致通过常规方式下载的视频无法直接播放。
🔍 问题发现
在研究微信视频号下载方案时,我们发现:
- 使用 WeChatVideoDownloader 等工具通过代理获取视频地址
- 下载的视频文件无法正常播放
- 通过十六进制分析发现文件头格式异常
1 | |
重要声明:本文仅供学习和研究目的使用,不鼓励、不支持任何形式的非法行为。请在使用时遵守相关法律法规。
🛠️ 准备工作
在正式开始逆向分析之前,我们需要启用微信开发者工具以便调试。
启用开发者工具
由于微信默认不会启用开发者工具,我们需要对微信的动态链接库进行修改:
- 找到
xweb-enable-inspect启动选项 - 修改 branch 指令
- 使该启动选项所在的分支永远执行
完成修改后,我们就能在微信视频号中打开开发者工具进行调试。

🔍 逆向分析
JavaScript 初步分析
首先打开一个视频,通过开发者工具我们可以看到很多网络请求。其中带有 stodownload 的就是下载的视频文件,但这些视频链接下载下来的内容是加密的。

通过分析发现,解密操作发生在文件下载完成后。查看请求发起位置,我们追踪到 worker_release.js 中的 g.send() 方法。

熟悉 JavaScript XMLHttpRequest 的开发者会发现,这正是发送请求的标准方法。向上查找,我们找到了返回值处理逻辑。

解密函数分析
通过分析,我们发现解密函数就是函数 M,参数分别为数据和 startIndex(文件的第几个字节):
1 | |
函数 M 的逻辑非常简单:
- 将数据和
decryptor_array进行异或运算 - 如果当前的
startIndex大于decryptor_array的长度,则不进行异或,保持原有数据

通过断点调试,我们发现 decryptor_array 的长度是一个常量:2^17 = 131072 字节。

加密策略推断
从 decryptor_array 的恒定长度可以推断出:
- 视频加密只作用于文件的前 131072 字节(128KB)
- 这样的加密策略是合理的,避免对整个视频进行加密解密时消耗过多资源
- 对于同一视频,
decryptor_array是一致的 - 不同的视频文件对应不同的
decryptor_array
经过搜索,我们发现 decryptor_array 的赋值仅在 wasm_isaac_generate 函数中进行。

而 wasm_isaac_generate 函数在代码中只被 wasm_video_decode.js 调用。
在 wasm_video_decode.js 中,wasm_isaac_generate 作为一个汇编函数,可以在 WebAssembly 中通过 _emscripten_asm_const_int 接口被调用。


🧩 WebAssembly 深入分析
WASM 文件处理
下载 wasm_video_decode.wasm 后,我们使用 wabt 工具将其转换为 .o 文件,以便在反编译软件中进行分析:
1 | |
将生成的二进制文件 wasm_video_decode.o 拖入反编译软件,搜索 _emscripten_asm_const_int 的调用。我们发现 wasm_isaac_generate 在函数 f378 处被调用。

解密器分析
通过断点和调用栈的检查,我们发现 worker_release.js 中的 decryptor.generate() 最终触发了 wasm_isaac_generate 的调用。
仔细分析揭示出 decryptor 也是 WebAssembly 环境中的一个对象,即 WxIsaac64。

经过研究,我们了解到 Isaac64 实际上是一个随机数生成算法。

解密流程推断
基于以上分析,我们可以合理推测解密流程:
graph TD
A[获取视频seed] --> B[初始化Isaac64算法]
B --> C[调用decryptor.generate()]
C --> D[WASM生成随机数]
D --> E[写回JavaScript赋值给decryptor_array]
E --> F[下载加密视频]
F --> G[前128KB数据与decryptor_array异或]
G --> H[视频解密完成]
decryptor使用视频对应的 seed 进行初始化- JavaScript 调用
decryptor.generate(),指示 wasm 在其内存中生成 2^17 即 131072 个随机数 - wasm 生成随机数后,通过
wasm_isaac_generate将这些随机数写回 JavaScript,赋值给decryptor_array
现在,我们知道了 decryptor_array 的来源,接下来的问题是确定初始化 Isaac64 算法的 seed 的来源。
WebAssembly 进一步分析
下载wasm_video_decode.wasm后,我们使用wabt工具将其转换为.o文件,以便在反编译软件中进行分析。
./path/to/wasm2c wasm_video_decode.wasm -o wasm_video_decode.c
cp /path/to/wasm-rt-impl.c .
cp /path/to/wasm-rt-impl.h .
cp /path/to/wasm-rt.h .
gcc -c wasm_video_decode.c -o wasm_video_decode.o
完成这些步骤后,我们得到一个二进制文件wasm_video_decode.o。将此文件拖入反编译软件,搜索_emscripten_asm_const_int的调用。我们发现wasm_isaac_generate在函数f378处被调用。

进一步通过断点和调用栈的检查,我们发现worker_release.js中的decryptor.generate()最终触发了wasm_isaac_generate的调用。
仔细分析揭示出 decryptor 也是 WebAssembly 环境中的一个对象,即WxIsaac64。

经过研究,我们了解到 Isaac64 实际上是一个随机数生成算法。

因此,我们可以合理推测:
decryptor 使用视频对应的 seed 进行初始化。
JavaScript 调用decryptor.generate(),指示 wasm 在其内存中生成 2^17 即 131072 个随机数。
wasm 生成随机数后,通过wasm_isaac_generate将这些随机数写回 JavaScript,赋值给decryptor_array。
现在,我们知道了decryptor_array的来源,接下来的问题是确定初始化 Isaac64 算法的 seed 的来源。
Tracebackbackbackbackback
🔎 Seed 追踪
接下来就是不停地打断点,查看调用栈,直到找到 seed 最早出现的地方。



简单来说,调用顺序为:
1 | |
💉 WeixinJSBridge 注入
那么 FinderGetCommentDetail 又是通过什么获取到信息的呢?继续追踪调用,我们发现 FinderGetCommentDetail 最后使用了 window.WeixinJSBridge.invoke 来获取数据。

window.WeixinJSBridge???那接下来就要逆向微信的通信协议了。我才懒得逆向这玩意。
立刻启动后备隐藏能源,发动注入模式!
1 | |
注入结果非常好,我们获得了需要的所有数据!


📌 总结
通过以上分析,我们得出了解密微信视频号视频的完整流程:
- 通过
FinderGetCommentDetail获取视频的decode_key(即 seed)、url、title 等信息 - 通过 seed 生成
decryptor_array - 通过 url 下载加密后的视频文件
- 将视频的前 128KB 加密段数据和
decryptor_array做异或运算即可完成解密
🛠️ 视频下载器实现方案
由于获取 seed 需要逆向微信协议,我不想在逆向这个协议上花费太多时间。
既然 WeChatVideoDownloader 已经使用代理获取视频地址,我们可以进一步使用中间人攻击来获取视频链接及对应的 decode_key。
只需将注入 WeixinJSBridge.invoke 的代码插入到某个 JS 文件中,当微信客户端请求视频链接时,就把获取到的视频链接发送到本地服务器。
这样不仅解决了 seed 和链接的问题,连视频标题也能获取到。
最后,下载完视频后,通过 seed 生成解密序列并对视频进行解密。
📝 写在后面
回顾这次的逆向工程过程,我们可以看到 WebAssembly 在现代网络安全和逆向工程领域扮演着越来越重要的角色。随着 WebAssembly 的普及,JavaScript 逆向逐渐演变为 WebAssembly 逆向。这不仅提高了代码的执行效率,同时也给逆向工程带来了更多的挑战和机遇。
相关链接
- 微信 v3.9.8.15
- wasm_video_decode.wasm v1.2.46
- worker_release.js v1.2.46
- wasm_video_decode.js v1.2.46
- wasm_video_decode_fallback.js v1.2.46
免责声明:本博客中提供的信息和过程仅供学习和研究目的使用。博主不鼓励、不支持并强烈反对任何形式的非法行为,包括但不限于未经授权的数据访问、破解或逆向工程。博客内容的使用应遵守相关法律法规以及道德规范。
读者在使用本博客中的信息时,应自行承担相应的风险和责任。博主不对由于使用、引用或依赖本博客中信息而产生的任何形式的损害或损失负责。此外,博主对于博客内容的准确性、完整性或适用性不作任何明示或暗示的保证。
请读者在使用本博客中的技术和信息时,始终保持合法、负责任的态度,尊重知识产权和隐私权。如果您不确定您的行为是否合法,或者您的行为可能会侵犯他人的权利,请在行动前咨询专业法律意见。
📚 相关资源
通过本次逆向分析,我们不仅解决了微信视频号视频解密的问题,更深入了解了现代Web应用中WebAssembly的使用方式。这为今后处理类似的技术挑战提供了宝贵的经验和思路。