环境:未登录
经过初步简单分析,在访问下面这个JS后,才生成的含有sign的链接:
https://static.hdslb.com/player/js/bilibiliPlayer.min.js?v=6b8deee3
https://bangumi.bilibili.com/player/web_api/v2/playurl?cid=34108497&appkey=84956560bc028eb7&otype=json&type=&quality=80&module=bangumi&season_type=4&qn=80&sign=873ad4e420b51ce157f31733353ba397
多次尝试发现,这个链接的sign是一个固定值,只有改变qn(清晰度)的时候,sign才发生改变
比如
https://bangumi.bilibili.com/player/web_api/v2/playurl?cid=34108497&appkey=84956560bc028eb7&otype=json&type=&quality=64&module=bangumi&season_type=4&qn=64&sign=52a7209153346b02983bc98a74d39ace
在其他浏览器下操作也是如此
https://bangumi.bilibili.com/player/web_api/v2/playurl?cid=34108497&appkey=84956560bc028eb7&otype=json&type=&quality=80&module=bangumi&season_type=4&qn=80&sign=873ad4e420b51ce157f31733353ba397
进一步分析
对JS格式化之后,搜索web_api/v2/ 很快可以定位到
继续顺藤摸瓜
再返回的json数据中开头是 accept_format
搜索得到
可以判断,这里是对接收到的数据解析,对视频地址进行播放
那么在这里添加一句,重定向JS
确实是对数据解析
把这个函数收起来,刚好可以发现这和最开始搜索的链接挨着的,同时发现调用了解析数据的函数,那么接口请求的链接也应该在这里
通过console可以看到
b就是接口链接
f.Hc值为true
f.reject是一个函数
this.url没有值
重新更改js,在这三个地方比较b的不同之处
可以看到后面两个地方b的值并没有改变,而在通过函数 b = c.a.B(b);后b直接成为了完整的接口链接 (实际上在执行这个函数前b的值为定值6330776) 输出函数c.a.B
该函数如下
function m(b, c) {
if (0 === c || !b) return "";
for (var d = 0, e, f = 0;;) {
e = T[b + f >> 0];
d |= e;
if (0 == e && !c) break;
f++;
if (c && f == c) break
}
c || (c = f);
e = "";
if (128 > d) {
for (; 0 < c;) {
d = String.fromCharCode.apply(String, T.subarray(b, b + Math.min(c, 1024)));
e = e ? e + d : d;
b += 1024;
c -= 1024;
}
return e
}
return v.IC(b)
}
同样的,多次console.log后,有以下结果:
无论何种清晰度都会执行下面这个函数来得到请求接口的完整链接
c.a.$B(b)
且b总是6330776
在被调用函数中
for (; 0 < c;) {
d = String.fromCharCode.apply(String, T.subarray(b, b + Math.min(c, 1024)));
e = e ? e + d : d;
b += 1024;
c -= 1024;
}
此循环只循环了一次,d的初始值是127;c的初始值是定值192;
第一次循环,自减1024位-832,循环结束。
e为完整链接,d在一次循环结束,即
d = String.fromCharCode.apply(String, T.subarray(b, b + Math.min(c, 1024)));
这一句执行了一次之后就是完整链接了
对于循环:
for (var d = 0, e, f = 0;;) {
e = T[b + f >> 0];
d |= e;
if (0 == e && !c) break;
f++;
if (c && f == c) break
}
添加console.log(b);console.log(f);
有如下结果:
即,b的值没有变化,f的值从1增加到192
对于console.log(e)结果如下(紧跟for循环中括号后)
实际上关键就是e,这一些数字是ASCII码,将其对应转换为字母数字,就是完整的视频接口请求链接
绕了半天,这里才是sign的算法入口,但是我也就止步于此了,完全没有明白这个函数是什么操作...
比如在
console.log(e)
for (var d = 0, e, f = 0;;) {
使用console.log(e),e是undefined
console.log(e)
e = T[b + f >> 0];
但这样在循环内使用使用console.log(e)
e又是有值的,为104
更神奇的是就算按下面这样
e = T[b + f >> 0];
console.log(e)
e首次的值也是104(没学JS,有理解错误请指正)
那这个T呢,又是什么
通过alert显示是这个,数据太多,无法显示完整,就是用console也没法完整输出
101,109,115,99,0,0,0,0,136,1,0,0,153,1,0,0,170,1,0,0,187,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,180,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,108,96,97,101,97,62,61,60,98,100,51,63,102,57,100,61,0,12,85,86,87,15,85,80,86,87,92,84,6,1,84,84,82,0,121,116,38,122,112,40,116,120,114,122,114,121,45,35,32,38,0,5,6,13,89,2,80,81,11,86,...,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
看起来是一组数字序列
根据
e = T[b + f >> 0];
来看,b是定值,f每次加1,如果说T是固定的,那么无论如何返回的链接应该是一样的,但没有,所以是每一次请求T就会有变化,但是这是如何进行的,不知从何下手。。
用了一个循环
for (var prop in T) {console.log("T." + prop + " = " + T[prop]);}
然后一直输出到1.3W,网页卡了,后面基本全是0
换了个姿势
切换清晰度,发现是一样的
但增加循环次数。发现似乎...T很长,没有规律
设定为12000次
这是最末尾的输出
根据对代码的统计,应该有10240个数
+1就是1024*10个数,JS前面有T.set([])
这种的东西,[]内有10240个数,应该和这个是对应的,但是没有发现什么关联...
完整的T序列
2018-7-10 新进展
W是一个长为16777216的数组(2^24,应该是一个没有上限的数组),通过取W的6330680到6330872位,即共192位的值,即ASCII码,再转换为字符即是接口链接。
现在的问题是W是在怎么产生的
v.RC = W = new Uint8Array(I);
这里W初始化(?)的长度为16777216,全0
在25861行左右有m([136, 1, 0, 0, 153, 1, 0, 0, 170, 1, 0这样的序列
调用的是25191行左右function m(c, d, f, g) {这个函数
注意这一句
if ("i8" === h) return c.subarray || c.slice ? W.set(c, l) : W.set(new Uint8Array(c), l), l;
那么此处是会改变W的值的,另有一处
这里验证了,应该是没起作用
需要考察的是下面这几个地方
5处是前面说的初始值
3处验证过,在sign有了之后才执行的,也可以不管
2处就是取W从6330680到6330872的值,随后按ASCII对应字符转换就是接口链接
4处的两个从表面看是不会对W有影响(修改之类),除非这个函数嵌套了1处的函数。
下面图是1处所在函数的情况
关注这几个地方
第一个地方,G.n是定值8
第二个地方,也是固定的东西
第三个地方
这个地方貌似也没执行,第四个地方也是。
最后一个明显是会执行函数m,但是是"i32",那么不会对W产生影响。
现在关心第一个。
。。
不过突然发现有漏了的,26112也是执行了m的
是固定的
测试发现这两个地方都只执行了一次,那就是固定值。
那现在分析这个地方
Fa.push只是也执行了一次
4次W.set中 ma均为1052144,同时测试了这四个地方的W在中间范围都是0
到现在好像还是没找到哪里真正改了W的值
把全部大写W的地方都大概看了下,,没发现什么东西。。好奇怪啊
这个函数l似乎也没有地方调用
难道是其他JS脚本调用?
其他发现,这个地方里面列表供256个数字
这个地方供2958个数字
有趣的是:
另外video.min.js也是有很多一样的部分的
也许是这个js?
先折腾到这里吧~~