前言

清一色的开篇,目的只为水一篇文章…
这次是Bilibili Web端直播心跳API一个加解密算法
去年写的东西,放着一直没怎么使用,一直懒就没写…
以下所有数据都脱敏处理或者打码,不要作测试数据…

Bilibili Live

如果研究的朋友,可能都抓过包看过数据包的情况
有两个关键请求,分别为reportEnterRoomreportHeartBeat
两个请求在不同状态下带入一个加密参数 s

reportEnterRoom

https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/E
E请求在心跳流程中只请求一次,进入房间

1
2
3
4
5
6
7
8
9
10
11
12
13
# E 1

id: [1,145,0,123456]
device: ["AUTO3915894629123456","799c882c-06de-4bfe-a358-98a76dccfa07"]
ts: 1595348574562
is_patch: 0
heart_beat: []
ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.64
csrf_token: 08jbtyz494rzim62c7k29mk7tjc8s5ez
csrf: 08jbtyz494rzim62c7k29mk7tjc8s5ez
visit_id:

{"code":0,"message":"0","ttl":1,"data":{"timestamp":1595348575,"heartbeat_interval":300,"secret_key":"seacasdgyijfhofiuxoannn","secret_rule":[2,5,1,4],"patch_status":2}}

is_patch == 0 -> heart_beat == [] 一般直接使用这个

1
2
3
# E 2
is_patch: 1
heart_beat: [{"s":"jjh64tcxjjjd062s2sfxfkrcey63a0z1jc9hrkjyy4d9436fib9wj0pynwmncpeib9i4ckjxmnkw1e0h41mn86fir47yzcafrspzrp05i9rnf0dbje6ndcsk3f1bm4th","id":"[6,235,1,123456]","device":"[\"AUTO3915894629123456\",\"7b9faf1a-cdd0-45a7-8355-e68972550341\"]","ets":1595248610,"benchmark":"seacasdgyijfhofiuxoannn","time":285,"ts":1595248894609,"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.64"}]

is_patch == 1 -> heart_beat == [**] 短时间内重复进出直播间触发

reportHeartBeat

https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/X
X请求在心跳流程中按次循环,必须先E再循环请求X

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# X 1
s: d6fb6f7fdef8de9262e2b27ff6ef185a8d2ff72ce68f0a3648797e146bd655d6f5aab5e8f46826cde306267de149ae439a8ed6c3ce1e22220f2af498be1d144f
id: [1,145,1,123456]
device: ["AUTO3915894629123456","799c882c-06de-4bfe-a358-98a76dccfa07"]
ets: 1595348575
benchmark: seacasdgyijfhofiuxoannn
time: 300
ts: 1595348874823
ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.64
csrf_token: 08jbtyz494rzim62c7k29mk7tjc8s5ez
csrf: 08jbtyz494rzim62c7k29mk7tjc8s5ez
visit_id: k5fj7uhwfn4

{"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595348875,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}}


# X 2
s: 8323ed71eac733c50956f46fbe10023826270197ee4af09c6ef036c1a798005298036de230bfc8ecde2e4018ee232884a2a813d89d12d701ab16f5c23d685ec9
id: [1,145,2,123456]
device: ["AUTO3915894629123456","799c882c-06de-4bfe-a358-98a76dccfa07"]
ets: 1595348875
benchmark: seacasdgyijfhofiuxoannn
time: 300
ts: 1595349175008
ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.64
csrf_token: 08jbtyz494rzim62c7k29mk7tjc8s5ez
csrf: 08jbtyz494rzim62c7k29mk7tjc8s5ez
visit_id: k5fj7uhwfn4

{"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595349175,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}}

# X 3
s: 369b18326a99fff5b5556da14039f807f21030e390de6f204a53d0cab0cccba7f0d0bcc60347f8fc43d9905be775f0c0fcdab4dd9bd6c8a52465f4a19b35cf36
id: [1,145,3,123456]
device: ["AUTO3915894629123456","799c882c-06de-4bfe-a358-98a76dccfa07"]
ets: 1595349175
benchmark: seacasdgyijfhofiuxoannn
time: 300
ts: 1595349475071
ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.64
csrf_token: 08jbtyz494rzim62c7k29mk7tjc8s5ez
csrf: 08jbtyz494rzim62c7k29mk7tjc8s5ez
visit_id: k5fj7uhwfn4

{"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595349475,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}}

# X 4
s: b9486ab176a70d444c7e34aa2f35c09270365fd15f5fc023036a426165d38a6fa831cde17de8a37007c53fcb204cfc0155167647c42bca263007068a42774592
id: [1,145,4,123456]
device: ["AUTO3915894629123456","799c882c-06de-4bfe-a358-98a76dccfa07"]
ets: 1595349475
benchmark: seacasdgyijfhofiuxoannn
time: 300
ts: 1595349775262
ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.64
csrf_token: 08jbtyz494rzim62c7k29mk7tjc8s5ez
csrf: 08jbtyz494rzim62c7k29mk7tjc8s5ez
visit_id: k5fj7uhwfn4

{"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595349775,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}}

Parameter

参数注意数据规律,除了参数s,以下几个参数比较重要

NAME DESCRIBE REMARKS
ts 请求时间 null
ets 可从E->X*n依次从回显中取值 null
id 大分区、小分区、轮次、长位直播间 null
secret_rule 加密规则 null
heartbeat_interval 请求之间的休眠 null
secret_key 加密规则 null

设备、版本不同可能存在参数差异

逻辑

这里只贴一下大概的流程,具体的细节可以看后面的代码
加密前明文主要是一些直播参数,以及dom、’window’、document
加密部分是一个wasm文件,带入参数以及secret_rule等加密
加密后密文是一个128位的HASH值
解密过程就是一场艰苦的和JS玩捉迷藏的游戏

进入直播间和循环心跳

外层调用心跳以及计算SIGN

初始化Wasm

调用Wasm加密Spyder (加密不止一轮)

Spyder本体 (cargo-web)

深度可以看看wasm2wat demo

Demo

只是贴出大概步骤,跳转并只不是一个js文件里发生

实现

仓库地址 哔哩哔哩 Web端直播加密心跳请求解析
代码逻辑比较简单,详情施工中

总结

文章写的比较乱不全,会贴出加解密部分,剩下的东西自己分析了
该文章代码只为学习,麻烦未经允许禁止转载哦

靠别人写全部代码,不太可能,大家都是鸽子,咕咕咕!

END.