最近有空研究了下小X通的视频协议,下面记录下研究过程

首先我们要了解下m3u8是什么

m3u8基础

首先我们需要了解什么时HLS,所谓HLS(HTTP Live Streaming)是一个由苹果公司提出的基于 HTTP 的流媒体网络传输协议。而m3u8是HLS协议的一部分,但是在直播,视频网站等用处很广泛。

HLS协议规定,视频的封装格式是TS(Transport Stream),除了TS视频文件本身,还定义了用来控制播放的M3U8文件(文本文件)。HLS协议的工作原理是把整个视频流分割成一个个小的TS格式视频文件来传输,在开始一个流媒体会话时,客户端会先下载一个包含TS文件URL地址的M3U8文件(相当于一个播放列表),给客户端用于下载TS文件。这样可以让用户更方便的选择视频节点播放,给用户更好的体验,其次提供了加密方式,可以更好的保护视频不被窃取。

下面是m3u8的一个基本字段

#EXTM3U:M3U8文件头,必须放在第一行。
EXT-X-MEDIA-SEQUENCE :第一个TS分片的序列号,一般情况下是0,但是在直播场景下,这个序列号标识直播段的起始位置; #EXT-X-MEDIA-SEQUENCE:0。
#EXT-X-TARGETDURATION:每个分片TS的最大的时长; #EXT-X-TARGETDURATION:10 ,表示每个分片的最大时长是10秒。
#EXT-X-ALLOW-CACHE:是否允许cache,#EXT-X-ALLOW-CACHE:YES 、#EXT-X-ALLOW-CACHE:NO,默认情况下是YES。
#EXT-X-ENDLIST:M3U8文件结束符。
#EXTINF:extra info,分片TS的信息,如时长,带宽等;一般情况下是 #EXTINF:<duration>,[<title>] 后面可以跟其他的信息,逗号之前是当前分片的TS时长。分片时长要小于 #EXT-X-TARGETDURATION 定义的值。
#EXT-X-VERSION:M3U8版本号。
#EXT-X-DISCONTINUITY:该标签表明其前一个切片与下一个切片之间存在中断。
#EXT-X-PLAYLIST-TYPE :表明流媒体类型。
#EXT-X-KEY:是否加密解析。例如:#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/video.key?token=xxx" 加密算法是AES-128,密钥通过请求 https://example.com/video.key?token=xxx 来获取,密钥请求回来以后存储在本地,并用于解密后续下载的TS视频文件。

请求流程

  1. 客户端发起对m3u8的请求,服务器在校验完成后会下载m3u8文件到本地。

  1. 客户端解析m3u8文件,在#EXT-X-KEY中找到密钥key地址,并访问拿到加密的密钥key。

  1. 客户端解析m3u8文件拿到分割文件的大小和对应ts文件地址,并访问拿到视频流。

  1. 客户端使用拿到的key地址和#EXT-X-KEY中对应的加密算法对视频流进行解密,播放视频。

所以我们看到这里真正重要的就几个部分,首先一定要找到m3u8文件的链接地址,然后从中找到#EXTINF和#EXT-X-KEY两个字段

  • #EXTIN字段中我们可以拿到ts协议流的分段大小信息,和视频流下载链接信息,并且可以通过start和end参数得到视频的最终大小

  • #EXT-X-KEY字段中我们可以拿到ts视频是否加密,如果加密可以拿到对应的加密方式和加密key地址。

  • 最后用得到的key和VI对ts文件使用openssl解密即可。

实战分析

了解了HLS的加密过程下面我们对小X通进行一个分析,首先我们通过抓包拿到了这个m3u8的链接地址,前面做了很多校验,但是不属于这个视频加解密分析范畴,这里不做分析。拿到以后我们可以对字段进行分析。如下图:

小X通m3u8视频流AES加密分析

下面对m3u8进行分析,我们可以得到如下信息:

  • #EXTIN中我们可以发现文件的分割大小,然后到最后可以看到文件的最终大小为141809727

v.f421220_0.ts?start=0&end=603679&type=mpegts
v.f421220_0.ts?start=141595968&end=141809727&type=mpegts
  • #EXT-X-KEY中我们可以发现文件的加密方式为AES-128的加密方式,对应得到下载key链接,并知道加密IV为0.

首先访问key地址,发现报错,提示缺少uid。

小X通m3u8视频流AES加密分析

可以看到这里需要校验对应的uid,js代码中也可以看到,那通过自有验证抓取uid。

小X通m3u8视频流AES加密分析

通过得到的uid信息得到对应的key文件

小X通m3u8视频流AES加密分析

然后拼接拿到整个是视频流

https://encrypt-k-vod.xet.tech/*****/****/drm/v.f421220_0.ts?start=0&end=141809727&type=mpegts&sign=*****&t=***&us=***

使用openssl解密

openssl aes-128-cbc -d -in 001.ts -out 001_dec.ts  -iv 00000000000000000000000000000000 -K ********************************
小X通m3u8视频流AES加密分析

但是发现报错,解密失败。哈哈我猜也不会这么简单

报错分析

既然报错了,那由可能是这个几个地方存在问题

  1. 选择的加密工具openssl工具解密出错

  1. 加密所用的key或IV出错

  1. 视频原始文件出错

具体分析尝试三个点可以发现

  1. 我尝试了自己使用AES加密文件后使用openssl解密,发现没有问题,证明不是openssl的问题

  1. 视频文件在页面可以播放,证明不是视频的问题

那么问题就出在key或iv上了,继续分析。如果我是写系统的人,为了加密视频通常会选择如下方式:

  1. 对key的二次加密,再来解密视频

  1. 实现一个自己的加密解密算法,来解密视频

逻辑推导一下可以看到对key的二次加密最简单快速,且最终可以调用公共的解密库执行,如果自己实现难度高而且bug多,估计多数不会选择。

那么我们从二次解密出发,首先再js中找关键字encrypted关键字,找到如下关键点:

小X通m3u8视频流AES加密分析

替换js并打印log尽然发现数组数据正好16位,可能是key文件

小X通m3u8视频流AES加密分析

但是抓到的是十进制数据,转换为十六进制

printf '%x\n' 84 43 *******

然后用得到的十六进制key进行解密操作

openssl aes-128-cbc -d -in uu.ts -out uu_out.ts -K ********************* -iv 00000000000000000000000000000000

发现并无报错,证明解密成功

小X通m3u8视频流AES加密分析

播放也没有问题,视频解密流程搞定。

小X通m3u8视频流AES加密分析

为了避免不必要的麻烦,对key等关键部分做了处理,本文只做研究分析,不想带来不必要的麻烦。

小结

最后来个小结,对整个流程分析下来还是很顺畅,难点也不多,真正难的算是对js的分析,js已经做了混淆,很多代码中找到对应的解密地址还是很麻烦,花了不少时间。

最后对视频加防下载的一些思考

  1. 目前大部分视频网站都采用的是HLS来进行视频流的获取和播放,因为首先对应的资源很丰富,各个云平台厂商均有对应的接口,方便开发者快速的搭建,但是对应的加密方式还是由很多问题

  1. 首先是加密方式,有些小厂商也不会对视频进行加密处理,直接可以进行下载播放,这种破解很简单就不提了。

  1. 有些选择了对m3u8文件进行加密,但是个人感觉这个和对key二次加密是一样的,均可以在js中找到对应的解密方法和最终的key或m3u8文件,这个只是时间问题,毕竟js文件在客户端,服务器不可控。

  1. 即便解密对应的key很费时间,但是如果采用对浏览器hook可以解决所有的加密方法,毕竟最终还是要在网页进行播放,只要抓取最终的数据流并dump就可以拿到最终解密完成的视频。

  1. 个人感觉加水印等防止小白录屏是可以,但是对懂一点技术的其实整个破解只是时间和熟练问题,我测试有些监控是自己通过c实现了一个加密解密算法,对视频进行加密保存,解密读取流程,虽然很安全,但是对.dll进行逆向还是可以找到对应的key和加密算法,只是时间问题。

  1. 说了这么多感觉什么都不安全,都可以被破解,事实也确实是这样,但是我们可以经常更新加密算法和加密key,来增加破解者的时间成本,也是可行的,让攻击者自己放弃,哈哈差不多就这样。