polyv加密key解密过程定位教程

February 2, 2021 · 分享 · 163次阅读

前言

  • 主要内容

    • 通用加密key解密过程定位技巧
    • polyv视频解密key还原

目标地址 https://www.exueshi.com/play/p201903981228671dd33a_5

过程

关于视频加密与解密

通过观察m3u8内容可以知道分段视频加密使用的应该是AES加密

但是它所请求返回的key大小是32字节,虽然AES确实可以是32字节作为key的,但是这里根据通常的经验来说,它肯定不是32字节的key

而对于在线视频文件,加密方案通常就那么几种,模式一般是下面这样

  • 服务端视频切片,采用某种加密方法,整体解密或者部分加密,提供文件下载服务
  • 客户端请求key,请求视频,根据加密方法,使用key解密

这其中,加强视频保护,通常在下面几个环节入手

  • 加强key下发给客户端过程的安全性,例如本案例中就是,返回的key无法直接使用
  • 采用非常规加密算法,例如使用RC4
  • 采用非常规加密方案,例如只加密特定部分,或者自定义加密部分
  • 客户端在黑盒中完成解密过程,最终输出画面,例如widevine

解密过程定位

对于本案例,它只是对key进行了保护,所以只需要将其解密为真正的key即可

在此提供几种定位加密key解密思路

  • 字符串搜索大法,在含有相关字符的附近下断点分析,例如

    • aes
    • aes-128
    • aes-cbc/aes-ecb
    • expandkey
    • importkey
    • inittable
    • decrypt
    • key
    • #EXT-X-KEY
  • 基于加密算法源代码特定分析

    • 各类加密算法往往会用到某些特定的数字或命名,在这些算法关键位置断点
    • 如果停在了断点位置,那么就可以根据这个断点向前分析调用栈寻找解密过程
  • 异常定位法

    • 对加密key进行替换,使解密为真实key过程出现异常,根据异常位置进行分析
  • 关键点追踪

    • 追踪请求完成后,观察key的内容都被进行了哪些处理

关键点追踪

方案一:单步追踪

首先查看请求调用栈,然后在loadInternal这个位置下debugger,等待key的请求

但是发现m3u8的请求也会停在这里,稍微修改一下,只有请求key的时候停下

接着就跟着走...

然后你就发现走了半天,走到了readystatechange,而这个方法正好在loadInternal下面

这个时候呢,稍微细心一点,你就能发现这里有一点似曾相识

这里有一个名为callbacks.onSuccess的函数,而且有response之类的名字

那么很可能就是在这里,拿到返回结果,进行了处理

一步一步走,可以确认这里确实是key请求的返回,那么接着进入callbacks.onSuccess

这下是不是就更加眼熟了,没错就是之前分析的内容加解密过程用到的函数,而t.data正是加密key

方案二:根据XMLHttpRequest特点快速定位

搜索XMLHttpRequest + loadInternal,会发现官方文档没有什么信息,但是能找到一些和hls相关的

不过这也很正常,毕竟这里是在播放视频,那么可以推测这里js的请求相当于是继承自XMLHttpRequest

那么它们应该有一些相似之处

这个时候,站在开发者角度,在请求完key之后,肯定需要去处理它,那么我们可以搜索XMLHttpRequest + 回调找一些例子

比如mozilla的说明

也就是说赋值给onreadystatechange的就是回调函数

至于这里怎么绑定的,具体原理就不展开了(我也不会),那么这样一下就能定位到请求成功后的处理函数了

再往后就和上面一样了

这里再扩展一下,搜一下onSuccess,然后下断点,就能找到每种请求分别绑定什么函数了

这样,后面再遇到类似的情况,就可以迅速找到需要的关键函数

异常定位法

比如我们在返回结果是key的时候,把它变成另外一个值,这里直接在js源码中修改的

尝试去掉token重定向到本地似乎不行,似乎有跨域限制,当然还有其他替换key内容的手段,抓包软件、重定向什么的

这里是把它从32位改成33位0,结果直接在解密的地方抛出异常了~~~

然后我们在出现异常的位置前面下断点,然后等它停在那里,然后再往上看一下调用栈,是不是就是解密过程了

解密过程代码分析

首先是函数D,进入后发现this.h就是字符h,而o()实际上是之前的md5函数

简言之,这里就是取一个变量minSeekHole的值,乘以2,转字符串,求md5

然后是取md5结果的前16位转为一个数组

接着把key用函数H进行了转,跳入可以看到就是转成了一个Uint8Array数组

而下一步解密用的IV变量I实际上是一个固定数组

最终解密结果放到了this.decryptkey*.frag.decryptdata.key

但是,但是这里并没有完,如果记忆力足够好,应该能记得之前At.m.c是三个参数

最后一个参数传了一个!0也就是true,显然这肯定不太一样

如果觉得一样可以手动验证一下之前的aes代码解密对比一下结果,就可以发现不一样

那么进入这个函数进行分析

进来就发现是一个if判断,这里要提一点

if (A, B, C){xxx}这种形式的判断,实际上判断的是最后一个条件C,但是前面的AB的代码实际上也会执行,具体参见下面的例子

演示代码

if(false){console.log('999')}
if(true){console.log('999')}
if(true, false){console.log('999')}
if(console.log('+++'), true){console.log('999')}

不过这里最后一个条件时this instanceof t肯定为真,因为这个函数最开始是new xxx来的,然后取反就是false,也就是说一定不会throw Error

但是前面部分是要计算的,现在来分析这一句话

void 0 === n && (n = !1), n || (i = H(i.map(function(t) {return t / 2}))), !(this instanceof t)

第三个参数ntrue,那么

  • void 0 === n 结果是 false
  • 不会进行 n = !1 这一步赋值
  • n第一个,之后还是true,那么||之后的部分就不会执行

第三个参数nundefined,那么

  • void 0 === n 结果是 true
  • 会进行 n = !1 这一步赋值 n 变成 false
  • n第一个,变成false,那么||之后的部分就会执行
  • i的值就会分别除以2

然后如果i传入的不是16位,那它就会被置为16位全0,也就是没有偏移量

按正常逻辑,我们可能推测_lastCipherblock还有对i的处理,但是由于之前验证iv过是没有变化时,是标准的aes

现在把截止这里对iv的处理,加入代码,然后验证,可以发现加密key解密结果与浏览器一致

也就是没有更多的处理(实际上某些网站_lastCipherblock这里还会继续处理,只是这里没有罢了,就不分析了)

那么最终key解密过程还原为下面的代码

小结

完成key的解密后,最终就能写出一个完整的解析脚本,只需要网页地址和视频VID

ENJOY 1

none

最后编辑于2个月前

添加新评论

avatar

未末

118

文章数

256

评论数

7

分类

新鲜出炉の评论

XstreamDL-CLI BUG修复记录
Andist
Andist2021-09-17

en……实在不好意思,代理我知道怎么启用了。我只勾选了自定义代理,但没有填写proxy参数,我太愚钝了对不起!!!

XstreamDL-CLI BUG修复记录
Andist
Andist2021-09-17

感谢您开发的这款软件,对于第一次下载mpd的小白而言很友好! 这段时间用下来就是有时候下载直连的海外视频流时可能因为网络状况不佳,会有下载不完整的问题,下载完进度没到100%,但是也合并解密了,不知道能否增加下载不完整在最后输出报错信息的功能呢? 以及我想请教一下如何让下载器使用小飞机的代理呢?我尝试在“使用自定义代理”的选项上勾选,但是好像命令行中没有变化? (另外我猜您图中的样本是在下载CP+上的用九柑仔店是吗?我也很喜欢这部剧,是我心目中排名第一的台剧哈哈)

XstreamDL-CLI BUG修复记录
未末
未末2021-09-16

要批量下载可以通过传入文件夹,文件夹内放要下载的m3u8。 要批处理调用建议使用N_m3u8DL-CLI。 你后面说的这个准确来说是混流操作,考虑到dash流,master m3u8的复杂性,目前不提供混流功能,这不是bug。混流请自行手动完成

白嫖某视频网站widevine解密key
未末
未末2021-09-16

用mp4dump查看对应视频的kid,对应使用

XstreamDL-CLI BUG修复记录
dehooy
dehooy2021-09-15

发现命令行并没有针对本地M3U8下载完成后输出文件名的参数,批处理测试会自动启动本地M3U8的文件名,这不方便批处理调用。另外 ,测试发现关于音视频分流的情况,下载解密后并不会合并这两路流,这是一个BUG,可参考某酷CMAF类型WV加密的M3U8