|
100精币
任意打开一个某鱼直播房间
https://www某鱼com/276200
浏览器会执行一个POST 其中q参数和e参数为加密参数
https://www某鱼com/lapi/live/getH5Play/276200
POST参数
ct=0&cr=0&tr=8&q=很长一串字符串&e=更长的遗传字符串
返回直播串流地址。
实战开始分析JS,浏览器打开某鱼某主播主页,等直播开始播放以后F12搜索JS文件:
关键断点
https://shark2.douyucdn.cn/front-publish/live-master/js/player_first/h5_video_206102c.js
- function onRuntimeInitialized() {
- var e = stateGetIn(['app',
- 'rid']),
- t = (new Date).getTime(),
- a = t.toString(16),
- i = parseInt('0x' + a.substring(0, a.length - 8), 16),
- o = parseInt('0x' + a.substring(a.length - 8, a.length), 16),
- r = getDid(),
- n = getCookie('auth') || '201806211659380f83e682207dd1293cea68f98662b1660083967948219fe20';
- Promise.resolve().then(function () {
- return rt = (new Date).getTime(),
- window.SQSSMURFNEEDALONGLONGLONGNAME.sqsneedalongname(e, i, o, r, n, 3186)
- })
复制代码 对window.SQSSMURFNEEDALONGLONGLONGNAME.sqsneedalongname 这一行下断点。
然后按F5刷新网页,此时断点停在此处。
跟进代码内部,发现是一段VM
- return function sqsneedalongname(arg0, arg1, arg2, arg3, arg4, arg5) {
- if (arguments.length !== 6) {
- throwBindingError('function sqsneedalongname called with ' + arguments.length + ' arguments, expected 6 args!');
- }
- var arg0Wired = argType0.toWireType(null, arg0); // unsigned int
- var arg1Wired = argType1.toWireType(null, arg1); // unsigned int
- var arg2Wired = argType2.toWireType(null, arg2); // unsigned int
- var arg3Wired = argType3.toWireType(null, arg3); // std::string
- var arg4Wired = argType4.toWireType(null, arg4); // std::string
- var arg5Wired = argType5.toWireType(null, arg5); // unsigned int
- <font color="#ff0000">var rv = invoker(fn, arg0Wired, arg1Wired, arg2Wired, arg3Wired, arg4Wired, arg5Wired);</font>
- arg3Wired_dtor(arg3Wired); // std::string
- arg4Wired_dtor(arg4Wired); // std::string
- <font color="#0000ff">var ret = retType.fromWireType(rv)</font>;
- return ret;
- }
复制代码 一路向下执行,来到这两句,是重点:
- var rv = invoker(fn, arg0Wired, arg1Wired, arg2Wired, arg3Wired, arg4Wired, arg5Wired);
复制代码 先跟进invoker函数体内部,发现还是一个VM
- (function(dynCall,rawFunction
- /*``*/) {
- return function dynCall_iiiiiiii_7(a1, a2, a3, a4, a5, a6, a7) {
- return dynCall(rawFunction, a1, a2, a3, a4, a5, a6, a7);
- };
- })
复制代码 重点在这一句:
return dynCall(rawFunction, a1, a2, a3, a4, a5, a6, a7);
这一句如果没有跟进内部,直接执行的话,那么加密参数的结果就会处理完毕了,存放到了emval_handle_array这个数组中第5个成员位置。
此时上面这一句的返回值为5。
- var rv = invoker(fn, arg0Wired, arg1Wired, arg2Wired, arg3Wired, arg4Wired, arg5Wired);
- <font color="#c0c0c0">arg3Wired_dtor(arg3Wired); // std::string
- arg4Wired_dtor(arg4Wired); // std::string</font>
- var ret = retType.fromWireType(rv);
复制代码 返回值5给了rv,同时retType.fromWireType(rv)这个方法就是从emval_handle_array数组的5号成员中拿出值,也就是最终的加密结果:
ct=0&cr=0&tr=8&q=820b3857a19851174d3aac83ab97ec91dc61081ecc48d75ab2686a8dfeba0ecc904c9470ee1655c518d8b00b3e82ef35e0efc5b33f68d0b810c99a220b3fa7f42ee5ffbb506d8af10bd10426484a6990f8ff665009fe6cf6f428ae6784becbee9aad653ced7ab4b643670cf1c9490232edc56d3eef756e33e2621bb852c1b2814010870cae2c7def4b014a11eabfaf314c2fe136e0e58004e2b844765c27e35a&e=0Cbee4b74b1e57fc25e2a44903c79c1e4cc48668554b6435a653a368aa28269fb8acde808ae43f7968ba96ebecf96eb3121e83fc87f3074611252b56704813928d3a883dd26c9730e5acfedf043c9f1f2667de04db712dff52130086615c53476d65b96bacdd5229c802770fb3c3eb478df8e2831890a581757413562b6575d08f90fe89e5ec09d04ca67d4c88633739e90d33a023d91fee8f6e3923366e8800ef62cb12dc0a17084247058e6fb898c6683fbc6061050a2f66b5beff32c42771262030f912701ddf941cc571280603ea86fbee864d9c9a7ceeb5205e79df8086e91922a464cd240dac5df1d09578eefb97
这里并没有拿到准确的算法,所以要跟进dyncall这个函数的内部。
进去以后发现是这样的:
- var dynCall_iiiiiiii = WasmModule["dynCall_iiiiiiii"] = function() {
- return WasmModule["asm"]["Ta"].apply(null, arguments)
- }
复制代码 arguments是一个数组,就是上面dynCall(rawFunction, a1, a2, a3, a4, a5, a6, a7)传递进来的8个变量.
同样的,到console里调试执行 “return WasmModule["asm"]["Ta"].apply(null, arguments)” 返回5,并且结果直接返回到了emval_handle_array数组中。
如果你跟进去的话你就会发现是一个死循环,一直在不停死循环,我尝试跟着他,跟了几个小时都跟不到关键算法,一直就在这里来换切换
跟进去以后是这样,再往里面跟就是另外一个和下面这个格式差不多的另外一个函数,反正就是一直循环,始终找不到关键算法。
- var stackSave = WasmModule["stackSave"] = function() {
- return WasmModule["asm"]["jb"].apply(null, arguments)
复制代码 别提搜"&q=","&e="这种特征字符串了,完全没有。。
某鱼的很多JS算法都是动态生成的,你在页面中或者JS文件中看到的JS仅仅是生成加密JS的JS,你必须通过这些JS来生成出加密的JS,再运行加密的JS才能得到加密结果。
所以想搜索关键字符串,是不可能的。
救救孩子吧,折腾很多天了。。。
|
最佳答案
查看完整内容
我找到了關鍵:
return WasmModule["asm"]["Ta"].apply(null, arguments)
return WasmModule["asm"]["jb"].apply(null, arguments)
別的都沒變,Ta變成了jb。
|