spacemeowx2 / DouyuHTML5Player

替换斗鱼的Flash弹幕播放器
MIT License
601 stars 98 forks source link

斗鱼原生 htm5 player beta #69

Closed steven7851 closed 6 years ago

steven7851 commented 6 years ago

斗鱼现在全房间都有 H5 播放器 Beta, 貌似不用 flash ? 算法也改了, 在 h5.js 里面有, API 用了 H5 版本的 希望大大能继续维护 DouyuHTML5Player, 斗鱼的播放器广告太多了 这是 h5.js 里面有关算法的部分, 没看懂是怎么算出来的, 看起来可以直接调用?

_ = rid
b = did
T = parseInt((new Date).getTime() / 6e4)
window[(0,A.default)(6893547,"1e80502f9d5999636333")](_,b,T)
suffix = 'v=220120180204&did=a1f0b03c19b8e6b65f35d98404061501&tt=25294716&sign=08006a05a523c95110d0f83b7a313bc9'
'https://www.douyu.com/swf_api/h5room/{rid}?{suffix}&cdn=ws-h5&nofan=yes&_t={T}'

v = rid
_ = did
b = parseInt((new Date).getTime() / 1e3)
window[(0, A.default)(256042, "9f4f419501570ad13334")](v, _, b)
suffix = 'v=220120180204&did=a1f0b03c19b8e6b65f35d98404061501&tt=1517682981&sign=ecbd75e4f9a54b098b2c2b883484942b'
postData = suffix + '&cdn=ws-h5&rate=0&ver=Douyu_H5_2018020301beta'
'https://www.douyu.com/lapi/live/getH5Play/{rid}'
spacemeowx2 commented 6 years ago

我看到了 WebSocket, nice

spacemeowx2 commented 6 years ago

sign是这样算出来的

window[(0,A.default)(6893547,"1e80502f9d5999636333")](_,b,T)

(0, x)可以化简成x, 其实就是调用了A.default, 参数是(6893547,"1e80502f9d5999636333")

往上翻可以看到 A = r(n(68))

n是webpack传进来的第三个参数, 也就是第68个模块, 改js把第一个函数改成

function(e) {
    console.log(e[68])
}

就可以知道是哪个模块, 可以看到一个 magic number 是 3337565984.

可以在webpack主函数里加上这行 window.require = t 然后 A = require(68) 得到 A 的值.

A.default(6893547,"1e80502f9d5999636333") 的结果是 "re7357c2c3"

从上面可以看到这第68个模块返回的只是一个字符串, 接下来是从window里取这个函数再执行, 也就是说真正的签名算法应该是在 "re7357c2c3" 这个函数里

在 h5.js 里粗略的搜索了一下并没有发现对这个函数的定义(搜索对window的操作) 我猜测是放到别的.js里了

P.S. 我在直播间里点右键并没有看到beta...是在内测吗还是我被拉黑了

UPDATE:

在scboy的直播间右键没有beta, 换了个直播间是有的.

那个 re7357c2c3 函数实际上就在html里面(...

spacemeowx2 commented 6 years ago

re7357c2c3 里就更简单了. 最后可以看到 eval 了一个字符串. 于是在他前面加个console.log就行.

console.log(strc)
return eval(strc)(abe0ddfd9bd7e730dd58cc0, abe0ddfd9bd7e730dd58cc1, abe0ddfd9bd7e730dd58cc2);

strc 的内容是这样的

(function(pp0, pp1, pp2) {
    var cb = pp0 + pp1 + pp2 + "220120180205";
    var rb = CryptoJS.MD5(cb).toString();
    var re = [];
    for (var i = 0; i < rb.length / 8; i++)
    {
      re[i] = (parseInt(rb.substr(i * 8, 2), 16) & 0xff) | ((parseInt(rb.substr(i * 8 + 2, 2), 16) << 8) & 0xff00) | ((parseInt(rb.substr(i * 8 + 4, 2), 16) << 24) >>> 8) | (parseInt(rb.substr(i * 8 + 6, 2), 16) << 24);
    }
    var k2 = [0x45b1f210, 0x3927c11c, 0x702140, 0x6dcb0bcc];
    for (var I = 0; I < 2; I++) {
        var v0 = re[I * 2],
        v1 = re[I * 2 + 1],
        sum = 0,
        i = 0;
        var delta = 0x9e3779b9;
        for (i = 0; i < 32; i++) {
            sum += delta;
            v0 += ((v1 << 4) + k2[0]) ^ (v1 + sum) ^ ((v1 >>> 5) + k2[1]);
            v1 += ((v0 << 4) + k2[2]) ^ (v0 + sum) ^ ((v0 >>> 5) + k2[3]);
        }
        re[I * 2] = v0;
        re[I * 2 + 1] = v1;
    }
    re[0] ^= k2[0];
    re[0] ^= k2[2];
    re[1] = (re[1] >>> (k2[1] % 16)) | (re[1] << (32 - (k2[1] % 16)));
    re[1] = (re[1] << (k2[3] % 16)) | (re[1] >>> (32 - (k2[3] % 16)));
    re[2] += k2[0];
    re[2] = (re[2] << (k2[2] % 16)) | (re[2] >>> (32 - (k2[2] % 16)));
    re[3] = (re[3] << (k2[1] % 16)) | (re[3] >>> (32 - (k2[1] % 16)));
    re[3] -= k2[3];
    re[0] = (re[0] << (k2[0] % 16)) | (re[0] >>> (32 - (k2[0] % 16)));
    re[0] ^= k2[2];
    re[1] = (re[1] << (k2[1] % 16)) | (re[1] >>> (32 - (k2[1] % 16)));
    re[1] ^= k2[3];
    re[2] -= k2[0];
    re[2] -= k2[2];
    re[3] ^= k2[1];
    re[3] ^= k2[3];
    {
        var hc = '0123456789abcdef'.split('');
        for (var i = 0; i < re.length; i++) {
            var j = 0,
            s = '';
            for (; j < 4; j++) s += hc[(re[i] >> (j * 8 + 4)) & 15] + hc[(re[i] >> (j * 8)) & 15];
            re[i] = s;
        }
        re = re.join('');
    }
    var rt = "v=220120180205" + "&did=" + pp1 + "&tt=" + pp2 + "&sign=" + re;
    return rt;
});

看上去 js 版的签名比 Flash 版的简单很多.

spacemeowx2 commented 6 years ago

Flash 实际上是执行 js 来切换播放器的 window.__player.switchPlayer(true);

spacemeowx2 commented 6 years ago

保护性 Close

hbprotoss commented 6 years ago

这个k2变量不是静态的,是前面eval出来的,没法改成别的语言😂

spacemeowx2 commented 6 years ago

@hbprotoss 跑一遍不就行了, 实在不行转到AST转其他语音...