机缘巧合之下侥幸免费获得某付费教程视频的观看权限,但期限只有一个多月。由于之前一些事情耽搁,等到有时间看已快到期限。于是打算下载本地留个备份。
先试试 IDM 自带的资源嗅探,寄
Pasted image 20240205005940.png (23.02 KB, 下载次数: 0)
下载附件
2024-2-5 13:05 上传
开始
抓m3u8
首先控制台抓包拿 m3u8 文件:
Pasted image 20240205010712.png (173.9 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
下载ts
然后下载 ts 文件:
简单写个 python 调用 IDM 爬一下
pip install idm
from idm import IDMan
downloader = IDMan()
fold_path = "D:\\video"
for i in range(0, xxx):
i = str(i).zfill(4)
url = f"https://略了/index_encrypt_00{i}.ts"
downloader.download(url, fold_path)
找key
从m3u8的文件信息中可知,使用的加密方法为AES128,获取key的url链接也知道
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="http://略/api/略?vod_id=略&app_id=略",IV=0x00000000000000000000000000000000
#EXTINF:4.000000,
略/index_encrypt_000000.ts
#EXTINF:4.000000,
略/index_encrypt_000001.ts
#EXTINF:4.000000,
略/index_encrypt_000002.ts
#EXTINF:4.000000,
略/index_encrypt_000003.ts
直接访问获取密钥的链接,得到以下内容:
{"msg":"success","code":"200","data":{"cipher_key":"MjEs*sN*****NTMD**U*Us****Y="}}
得到密钥是一串base64编码,在线解码即可:
Base64 编码/解码 - 在线工具 (toolhelper.cn)
Pasted image 20240205012738.png (57.43 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
手动新建一个key.key文件,用Hex编辑器将解码得到的16个数字填进去
Pasted image 20240205013158.png (68.42 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
推荐使用vscode的扩展:Hex Editor
Pasted image 20240205013309.png (22.55 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
之后顺便把index.m3u8文件中这行:
#EXT-X-KEY:METHOD=AES-128,URI="http://略/api/略?vod_id=略&app_id=略",IV=0x00000000000000000000000000000000
改为:
#EXT-X-KEY:METHOD=AES-128,URI="key.key",IV=0x00000000000000000000000000000000
最后将下载到的所有.ts、key.key、index.m3u8文件都放在同一个文件夹内,在shell中执行下面的命令:
ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,crypto,tcp" -i index.m3u8 -c copy out.ts
注:使用该命令需要下载ffmpeg,如果你装有scoop,可执行scoop install ffmpeg命令直接安装,其他下载方法我没尝试过,烦请自行搜索
然后........
Pasted image 20240205014745.png (888.34 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
就寄了......悲
为什么呢,因为直接访问链接拿到的密钥是错的
然后只能看源码了
根据观察大佬们得来的经验,从ts的启动器入手:
Pasted image 20240205015520.png (113.1 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
进去之后,根据观察大佬们的经验,搜索decryphtdata.key之类的关键词
总共找到三个结果,打断点,发现原本播放的视频断了,所以一般而言,这个this.decryphtdata.key的值就应该是真的密钥了
Pasted image 20240205021215.png (161.02 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
但是!!
AES128加密的密钥不应该是16位吗?这个密钥怎么是47位???
根据观察大佬的文章,判断这个key是被二次加密过,那就接着找解密key的代码
接着查看另外两个结果,发现下面这些相关代码:
Pasted image 20240205020319.png (130.49 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
不懂直接问GPT:
这段代码是一个方法,名为"decryptBuffer",接受两个参数e和t。在方法内部,调用了this.decrypter对象的decrypt方法,传入了e、this.decryptdata.key.buffer和this.decryptdata.iv.buffer作为参数。这个方法的作用是使用decrypter对象对e进行解密,使用this.decryptdata.key.buffer和this.decryptdata.iv.buffer作为解密所需的key和iv,将结果存储在t中。
然后我们搜索decrypter,找到这个:
Pasted image 20240205024716.png (94.84 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
问GPT:
这段代码是一个方法,名为"push",接受多个参数。在方法内部,首先对参数进行一些判断和处理,然后调用了this.decrypter对象的decrypt方法,传入了e、t.key.buffer和t.iv.buffer作为参数。当解密完成后,触发了一个事件并调用了pushDecrypted方法,将解密后的数据和其他参数传入。如果不需要解密,直接调用了pushDecrypted方法,将原始数据和其他参数传入。这段代码主要实现了对数据进行解密和处理后推送到指定位置的功能。
那么这里应该是key的解密程序了,然后打断点查看值:
Pasted image 20240205025438.png (208.93 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
没错确实是16位,把值像前面一样写进key.key文件,
解密
然后就是ts、m3u8、key.key放在一个文件夹下,执行命令:
ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,crypto,tcp" -i index.m3u8 -c copy out.ts
大功告成,耶(截图是后面补的)
Pasted image 20240205122935.png (381.07 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
参考文章
非常感谢一下大佬的文章,给了非常非常大的帮助,本文的也基本是仿照大佬写的
写在最后
蒟蒻第一次心血来潮搞这个,网上找了好多教程,虽然自己写的找key的过程就几句话,实际做的过程中卡了好长时间,还是自己太菜了,比如一开始找到的key为什么是47位,其实是因为base64解码出来的一串数组,像下面这样:
28,99,99,08,03,00,99,99,99,99,99,99,99,99,99,54
它的带逗号的,$2*16+15 =47$ ,这也是为什么这里44会反复出现
Pasted image 20240205124836.png (30.76 KB, 下载次数: 0)
下载附件
2024-2-5 13:06 上传
就想这种一个简单的问题卡了好长时间........
免责声明
本人仅仅用于个人学习。任何人不得将上述内容用于商业或者非法用途。