首页
社区
课程
招聘
[原创]微信视频号视频加密逆向
发表于: 2023-12-1 22:36 21632

[原创]微信视频号视频加密逆向

2023-12-1 22:36
21632

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

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

原文链接: here

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

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

最后实现效果如图下

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

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

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

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

查看请求是从哪行代码发起的,我们可以追踪到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了

下载wasm_video_decode.wasm后,我们使用wabt工具将其转换为.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实际上是一个随机数生成算法。

因此,我们可以合理推测:

现在,我们知道了decryptor_array的来源,接下来的问题是确定初始化Isaac64算法的seed的来源。

接下来就是不停的打断点,看call stack, 直到找到seed最早出现的地方就行了。

简单来说呢就是顺序就是从FinderGetCommentDetail(objectid)->objectDesc.media.decodeKey->seed

那么FinderGetCommentDetail又是通过什么获取到信息的呢。继续追踪调用。可以发现FinderGetCommentDetail最后使用了window.WeixinJSBridge.invoke来获取数据。

window.WeixinJSBridge ???那接下來就要逆向微信的通信协议了。这边有点不想做。所以就没做。

立刻启动后备隐藏能源,发动注入模式

总之结果很好,获得了需要的所有数据

总之为了让WechatVideoDownloader能够解密,我思考了以下的思路

由于获取seed需要逆向微信协议,我不想在逆向这个协议上花费太多时间。

既然WechatVideoDownloader已经使用代理获取视频地址,我们可以进一步使用中间人攻击来获取视频链接及对应的decode_key

只需将注入WeixinJSBridge.invoke的代码插入到某个JS文件中,当微信客户端请求视频链接时,就把获取到的视频链接发送到本地服务器。

这样不仅解决了seed和链接的问题,连视频标题也能获取到。

最后,下载完视频后,通过seed生成解密序列并对视频进行解密。

最后的劫持代码

proof of work

CHATGPT生成的。

aynakeya @ ThinkStation]:~/workspace/weixinshipin
01:59:21 $ xxd -l 32 v2.bin
00000000: 75a2 b80f 5db2 528b af76 c5f0 9407 a7e9  u...].R..v......
00000010: 4c31 99a8 60ef a5de c64e ce1e 3ab1 6e74  L1..`....N..:.nt
aynakeya @ ThinkStation]:~/workspace/weixinshipin
01:59:21 $ xxd -l 32 v2.bin
00000000: 75a2 b80f 5db2 528b af76 c5f0 9407 a7e9  u...].R..v......
00000010: 4c31 99a8 60ef a5de c64e ce1e 3ab1 6e74  L1..`....N..:.nt
00000000: 0000 0020 6674 7970 6973 6f6d 0000 0200  ... ftypisom....
00000010: 6973 6f6d 6973 6f32 6176 6331 6d70 3431  isomiso2avc1mp41
00000000: 0000 0020 6674 7970 6973 6f6d 0000 0200  ... ftypisom....
00000010: 6973 6f6d 6973 6f32 6176 6331 6d70 3431  isomiso2avc1mp41
./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
./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
(function () {
    function wrapper(name,origin) {
        console.log(`injecting ${name}`);
        return function() {
            let cmdName = arguments[0];
            console.log(`${name}("${cmdName}", ...) => args: `);
            console.log(arguments[1])
            if (arguments.length == 3) {
                let original_callback = arguments[2];
                arguments[2] = async function () {
                    console.log(`${name}("${cmdName}", ...) => callback result (length: ${arguments.length}):`);
                    if (arguments.length == 1) {
                        console.log(arguments[0]);
                    }else {
                        console.log(arguments);
                    }
                    return await original_callback.apply(this, arguments);
                }
            }
            let result = origin.apply(this,arguments);
            return result;
        }
    }
    window.WeixinJSBridge.invoke = wrapper("WeixinJSBridge.invoke",window.WeixinJSBridge.invoke);
})()
(function () {
    function wrapper(name,origin) {
        console.log(`injecting ${name}`);
        return function() {
            let cmdName = arguments[0];
            console.log(`${name}("${cmdName}", ...) => args: `);
            console.log(arguments[1])
            if (arguments.length == 3) {
                let original_callback = arguments[2];
                arguments[2] = async function () {

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 18
支持
分享
最新回复 (19)
雪    币: 2904
活跃值: (1337)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
2
6
2023-12-2 13:49
1
雪    币: 2948
活跃值: (30846)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2023-12-2 20:57
2
雪    币: 2164
活跃值: (1963)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
xweb-enable-inspect怎么修改?直接修改文件会被还原吧?
2023-12-3 00:35
1
雪    币: 129
活跃值: (333)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xed
5
修改文件后导出替换wechatwin.dll或者启动注入修改
2023-12-4 14:19
1
雪    币: 123
活跃值: (1242)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
哪位巨佬给我解惑下xweb-enable-inspect这个修改对微信小游戏,小程序是否同样适用?
2023-12-4 17:25
1
雪    币: 4037
活跃值: (4777)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享 
2023-12-4 18:59
0
雪    币: 2164
活跃值: (1963)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
胡家二少 哪位巨佬给我解惑下xweb-enable-inspect这个修改对微信小游戏,小程序是否同样适用?
没有用,首先就不知道大佬咋改的,改了会被还原,会被封号。敬请查阅腾讯微信使用条款和隐私政策。
2023-12-4 19:01
1
雪    币: 9872
活跃值: (6706)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
小程序可以打开调试工具吗
2023-12-4 20:26
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
666
2023-12-11 17:53
0
雪    币: 203
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
其实只需要抓到包含正确token的直链即可
2023-12-12 22:56
0
雪    币: 1458
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
update: 实际上就是isaac64算法,一动没动过。
2023-12-13 20:01
1
雪    币: 32
活跃值: (512)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
Aynakeya update: 实际上就是isaac64算法,一动没动过。
搜了一个go的isaac64算法尝试了一下 但是不一样 真的是isaac64算法吗 能给一个例子看看么 谢谢
2023-12-29 14:21
0
雪    币: 26
活跃值: (105)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
小程序是xdebug
2024-1-5 10:11
0
雪    币: 313
活跃值: (2267)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
是不是可以直接劫持decryptor_array的结果发送给客户端
2024-1-25 14:13
0
雪    币: 313
活跃值: (2267)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
执念成狂 是不是可以直接劫持decryptor_array的结果发送给客户端
测试了下确实可以,写了个下载工具,这是完整代码: https://github.com/kanadeblisst00/WechatVideoSniffer
2024-1-27 18:17
0
雪    币: 548
活跃值: (2374)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
执念成狂 测试了下确实可以,写了个下载工具,这是完整代码: https://github.com/kanadeblisst00/WechatVideoSniffer
十分感谢!正好工作中需要下载几个微信视频,用你的微信python库写了个根据工作群内容自动回复收到的工具。
2024-1-28 11:04
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
通过seed生成decryptor_array 如何做到?
感谢.
2024-4-13 12:07
0
雪    币: 240
活跃值: (85)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
qmzyy 其实只需要抓到包含正确token的直链即可
这个好像不行了 只能抓下载链接 然后直接解密视频
2024-5-18 21:03
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
大佬一看就是逆向技术大佬能帮个忙不,有偿服务
2024-7-16 18:58
0
游客
登录 | 注册 方可回帖
返回
//