通过抓包下载微信小程序中的视频

有这个需求是因为《无界·线上艺术》在春节上架了单雯施夏明的传承版昆曲《牡丹亭》,是我一直在寻找的演出视频。她/他们是我眼中这个时代最好的杜丽娘柳梦梅,一定要下载收入资源库。

单雯 施夏明 牡丹亭

You-GetDownie是我常用的下载工具,支持所有主流视频网站,而且Downie还可以用User-Guided Extraction模式手动下载不支持网站的内容。不过它们都需要视频所在网页的URL链接才能解析,而这个小程序播放器并非公开网页,没有暴露出任何URL,所以此路不通。

只剩下一种方法,抓包,无论软件怎么隐藏,都必须通过网络把服务器上的源视频下载到本地才能播放,一定会产生大量TCP数据包,通过Wireshark追踪一定能找到源视频地址。主流视频平台一般会采用诸如分段、加密等方式增加解析难度,但我不觉得一个冷门的小公司产品会这么做,试试看。

Wireshark

首先解决如何用MacWireshark捕捉手机端数据包的问题,一种方式是用连接有线网络的Mac开启网络共享创建Wi-Fi热点,手机连接此热点后产生的所有网络数据都会通过Mac,即可被捕捉。另一种方式是先用Charles之类的软件在Mac上创建代理服务,然后同局域网内手机设置代理指向它,也可以实现转发网络数据包。但iPhone内置的代理只有HTTP Proxy,不借助第三方软件只能把HTTP通信包转发到Mac,而有些视频流并非HTTP协议,所以连接Mac热点更好一些。

只有连接有线网络的Mac可以开启Wi-Fi共享。

mac sharing

手机播放视频时发现Wireshark捕捉到大量与同一个IP交互的TCP数据包,上层是HTTP协议:

wireshark

试着Follow它的TCP Stream,发现明文HTTP请求:

wireshark

图中HostGET组合就是视频的URL地址:

http://130*********.vod2.myqcloud.com/32a5c501vodcq130*********/9111a3b75285890814193748493/************UA.mp4

HTTPRang参数和206响应码可以看出客户端是在以分段方式请求数据,视频总长度1,313,589,669字节,本次请求的是0~262,143字节。这种分段请求是播放器加载网络媒体的一种实现方式,根据进度条位置按需下载对应的数据片段,而非不切实际把整个视频下载下来。不过普通MP4视频是嵌套结构,客户端必须从头加载而不能只靠中间的部分数据播放,这种方式要求源视频必须是特殊的Fragmented MP4。另一种常见播放方式是HLS,先把原视频切割成小片段,生成作为索引的M3U8文件,客户端再按需请求这些片段,实现渐进式加载播放。

用浏览器打开URL,运气不错,无须授权并且是未分割的完整视频,可以直接保存到本地。

单雯 牡丹亭

惊鸿一瞥,单雯施夏明【山桃红】后半段,我真的是第一次看到✨。

HTTPS

不过大部分情况下从Wireshark看到的并不是HTTP,而是密密麻麻的TLS,即加密HTTPS

wireshark

Follow它的TCP Stream会看到加密后的HTTP报文,理所当然一片乱码,分辨不出有效信息:

wireshark

本以为Wireshark能像Charles那样把自己的根证书导入系统再以中间人方式监听HTTPS通信,但搜索一番发现并不可以,它比Charles更底层而不能这样做。

仅有的两种方法在下载微信视频时都不可行:

  1. 要求提供服务端的HTTPS私钥(怎么可获得🤷🏻)。
  2. 要求从浏览器导出HTTPS使用的实际通信密钥(微信小程序视频不可能用浏览器打开🤷🏻)。

车到山前必有路,既然已经知道客户端是使用HTTPS分段请求资源的方式下载视频,那就用Charles看看:

charles

成功解密,完整URL映入眼帘,左边一列是大量分段请求,Charles媒体标记也验证了它们就是下载的视频片段。

尾声

之前一直以为网络视频都是先在服务端被分割后再供客户端点播,即HLSM3U8,原来也可以不分割,让客户端使用HTTP分段请求特性按需下载片段。这并非从书上看到的结论,而是自己在需求驱动下一步步剥茧抽丝发现的,这些探索过程十分有趣。

arrow_upward