游客发表
去年冬天,加密一个做在线教育的视频朋友发来一个MP4文件,说课程视频被加密了,文件学生只能在指定App里看,破解问有没有办法导出来。加密我拿过来一看,视频文件头正常,文件能播放前几秒,破解后面全是加密花屏。这不是视频普通的DRM,是文件那种私有加密——视频流被AES分段加密,密钥藏在App的破解so库里面。
很多人以为MP4加密就是加密加个密码,输对了就能看。视频完全不是文件。真正的视频加密分两种:一种是容器层加密,比如给整个MP4文件套个壳,播放时解密;另一种是流加密,把视频数据切成小块,每块用不同密钥加密,播放器边解密边渲染。前者容易破,后者麻烦得多。
我遇到的这个属于后者。用ffmpeg分析,发现moov box里多了个uuid box,里面写着加密方案标识。视频轨道的数据全部被替换成了加密后的密文,连NALU起始码都改了。普通播放器直接报错,只有他们自己的播放器能识别。
破解的第一步是抓密钥。安卓端相对容易,因为so库虽然混淆了,但密钥最终要传给解密函数。用frida hook住AES_set_decrypt_key或者CCCrypt,打印参数,密钥就出来了。iOS端麻烦些,但如果有越狱设备,用frida或者cycript也能搞定。我花了大概三个小时,在模拟器里跑他们的App,hook到了密钥——一个32字节的十六进制串,每播放一个视频会变一次,但算法固定。
拿到密钥后,事情就简单了。写个Python脚本,用pycryptodome按他们的分段规则解密,然后重新封装成标准MP4。分段规则需要逆向:他们用的是CBC模式,每个分段前16字节是IV,后面是密文。分段大小不固定,跟视频时长有关,但能从文件结构里推出来。
有个坑:音频轨道没加密,只有视频轨加密了。所以解密完视频后,得把音频轨原样合并回去。用ffmpeg的concat demuxer,或者直接操作MP4的box结构,把解密后的视频样本替换进去。我选了后者,更干净。
整个过程最耗时的不是解密本身,是逆向他们的分段逻辑。他们用了自定义的填充方式,不是标准的PKCS#7,而是每个分段末尾补0x00到16字节对齐。如果按标准方式解,最后几个字节会出错,导致画面底部出现绿条。我调了两次才确认这个细节。
有人问,那DRM呢?Widevine、FairPlay那种。那是另一回事。Widevine的密钥在TEE里,普通hook拿不到,得用CDM漏洞或者设备指纹伪造。FairPlay更封闭,基本只能靠录屏。但国内很多“加密视频”根本没用商业DRM,就是自己写的AES,密钥藏在App里,防君子不防小人。
说句实在话,这种私有加密的强度取决于逆向成本。如果只是为了防止普通用户随便拷贝,够用了。但如果有人愿意花几个小时逆向,基本都能破。我见过最离谱的,密钥直接硬编码在so里,连混淆都没做,用strings就能搜出来。
最后那个朋友的问题解决了,视频导出来了,画质没损失。他问我能不能写个工具,我说没必要,这种加密方案每家公司都不一样,写通用工具不如每次手动分析。他笑了笑,说那算了,反正就这一次。
其实MP4加密破解这事,技术门槛不高,但耐心要求高。你得懂MP4的box结构,懂AES的几种模式,懂一点逆向。缺一个,就会卡在某个环节。我见过有人卡在密钥提取上,有人卡在重新封装上,还有人卡在音频视频同步上。每个环节都有坑,但每个坑都能填。
友情链接