微信视频号视频加密逆向

tl;dr

拿WxIsaac64(Isaac64的变种?)生成2^17个字节。然后和视频的前2^17字节做异或。

前言

略去, 总之就是WeChatVideoDownloader不能用了。

原文链接: here

准备工作

在正式开始逆向之前,我们首先需要能够在微信视频号中打开开发者工具,由于微信默认肯定是不会启用的,所以我们要对微信的某个动态链接库进行小小的修改。

总之就是找到xweb-enable-inspect这个启动选项,修改branch指令,这个启动选项所在的分支变成永远执行就行了。

最后实现效果如图下

逆向

Javascript初步分析

首先随便打开一个视频,我们可以看到很多请求。其中带有stodownload的就是下载的视频文件,但这些视频链接下载下来的内容是加密的。

先看一下加密前的视频文件头,我们可以明显发现,它的文件头格式并不正确。

1

2

3

4

aynakeya @ ThinkStation]:~/workspace/weixinshipin

01:59:21 $ xxd -32 v2.bin

0000000075a2 b80f 5db2 528b af76 c5f0 9407 a7e9  u...].R..v......

000000104c31 99a8 60ef a5de c64e ce1e 3ab1 6e74  L1..`....N..:.nt

对比之下,一个正常的mp4文件的文件头应该如下所示:

1

2

000000000000 0020 6674 7970 6973 6f6d 0000 0200  ... ftypisom....

000000106973 6f6d 6973 6f32 6176 6331 6d70 3431  isomiso2avc1mp41

那么确认了文件被加密。那么我们要从哪里开始呢。因为解密必然是文件下载完成后才解密的。所以解密的函数或者过程很有可能就在文件下载完成后。

查看请求是从哪行代码发起的,我们可以追踪到worker_release.js中的g.send()

 

这个时候,写过Javascript XMLRequest的人可能就很熟悉这个了,在完成所有callback设置之后,发送请求用的就是.send(),所以往上翻,我们可以找到如下的返回值处理。 

里我们可以发现解密函数就是函数M,参数分别为数据和startIndex(也就是文件的第几个byte)

函数M非常的简单易懂,把数据和decryptor_array进行异或即可。如果当前的startIdx大于decryptor_array的长度,则不进行异或,不改变原有数据。

 如果我们在这个函数M的地方打个断点,我们可以发现这个decryptor_array的长度实际上是一个常量2^17 = 131072 (一直都是这个长度)

从这里我们可以推断出,decryptor_array的长度是有限的。

我们从decryptor_array的恒定长度可以推断出,视频加密只作用于文件的前131072字节。这样的加密策略似乎合理——如果需要对整个视频数据进行加密和解密,那么播放视频时消耗的资源可能会显著增加。

(虽然DRM好像就是全文加密的,我也不太了解就是了)

另外,我们还发现,对于同一视频,decryptor_array是一致的。不同的视频文件则对应不同的decryptor_array。这表明decryptor_array是通过某种特定的方法生成或获取的。

经过搜索,我们了解到decryptor_array的赋值仅在wasm_isaac_generate函数中进行。

 

wasm_isaac_generate函数在代码中只被一个地方调用,即wasm_video_decode.js

wasm_video_decode.js中,wasm_isaac_generate作为一个汇编函数,可以在WebAssembly中通过_emscripten_asm_const_int接口被调用。

 

那么接下来,就要开始逆向可爱的的wasm了

WebAssembly 进一步分析

下载wasm_video_decode.wasm后,我们使用wabt工具将其转换为.o文件,以便在反编译软件中进行分析。

1

2

3

4

5

./path/to/wasm2c wasm_video_decode.wasm -o wasm_video_decode.c

cp /path/to/wasm-rt-impl.c .

cp /path/to/wasm-rt-impl.h .

cp /path/to/wasm-rt.h .

gcc -c wasm_video_decode.c -o wasm_video_decode.o

完成这些步骤后,我们得到一个二进制文件wasm_video_decode.o。将此文件拖入反编译软件,搜索_emscripten_asm_const_int的调用。我们发现wasm_isaac_generate在函数f378处被调用。

进一步通过断点和调用栈的检查,我们发现worker_release.js中的decryptor.generate()最终触发了wasm_isaac_generate的调用。

仔细分析揭示出decryptor也是WebAssembly环境中的一个对象,即WxIsaac64

经过研究,我们了解到Isaac64实际上是一个随机数生成算法。 

猜你喜欢

转载自blog.csdn.net/q2919761440/article/details/135024262