开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 2213|回复: 6
收起左侧

[完成] 救救孩子吧 某鱼算法 javascript

 关闭 [复制链接]
结帖率:94% (15/16)
发表于 2019-10-16 04:43:59 | 显示全部楼层 |阅读模式   四川省巴中市
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
  1. function onRuntimeInitialized() {
  2. var e = stateGetIn(['app',
  3. 'rid']),
  4. t = (new Date).getTime(),
  5. a = t.toString(16),
  6. i = parseInt('0x' + a.substring(0, a.length - 8), 16),
  7. o = parseInt('0x' + a.substring(a.length - 8, a.length), 16),
  8. r = getDid(),
  9. n = getCookie('auth') || '201806211659380f83e682207dd1293cea68f98662b1660083967948219fe20';
  10. Promise.resolve().then(function () {
  11. return rt = (new Date).getTime(),
  12. window.SQSSMURFNEEDALONGLONGLONGNAME.sqsneedalongname(e, i, o, r, n, 3186)
  13. })
复制代码
对window.SQSSMURFNEEDALONGLONGLONGNAME.sqsneedalongname 这一行下断点。

然后按F5刷新网页,此时断点停在此处。
跟进代码内部,发现是一段VM

  1. return function sqsneedalongname(arg0, arg1, arg2, arg3, arg4, arg5) {
  2. if (arguments.length !== 6) {
  3. throwBindingError('function sqsneedalongname called with ' + arguments.length + ' arguments, expected 6 args!');
  4. }
  5. var arg0Wired = argType0.toWireType(null, arg0); // unsigned int
  6. var arg1Wired = argType1.toWireType(null, arg1); // unsigned int
  7. var arg2Wired = argType2.toWireType(null, arg2); // unsigned int
  8. var arg3Wired = argType3.toWireType(null, arg3); // std::string
  9. var arg4Wired = argType4.toWireType(null, arg4); // std::string
  10. var arg5Wired = argType5.toWireType(null, arg5); // unsigned int
  11. <font color="#ff0000">var rv = invoker(fn, arg0Wired, arg1Wired, arg2Wired, arg3Wired, arg4Wired, arg5Wired);</font>
  12. arg3Wired_dtor(arg3Wired); // std::string
  13. arg4Wired_dtor(arg4Wired); // std::string
  14. <font color="#0000ff">var ret = retType.fromWireType(rv)</font>;
  15. return ret;
  16. }
复制代码
一路向下执行,来到这两句,是重点:
  1. var rv = invoker(fn, arg0Wired, arg1Wired, arg2Wired, arg3Wired, arg4Wired, arg5Wired);
复制代码
先跟进invoker函数体内部,发现还是一个VM
  1. (function(dynCall,rawFunction
  2. /*``*/) {
  3. return function dynCall_iiiiiiii_7(a1, a2, a3, a4, a5, a6, a7) {
  4.     return dynCall(rawFunction, a1, a2, a3, a4, a5, a6, a7);
  5. };

  6. })
复制代码
重点在这一句:
return dynCall(rawFunction, a1, a2, a3, a4, a5, a6, a7);

这一句如果没有跟进内部,直接执行的话,那么加密参数的结果就会处理完毕了,存放到了emval_handle_array这个数组中第5个成员位置。
此时上面这一句的返回值为5。


  1. var rv = invoker(fn, arg0Wired, arg1Wired, arg2Wired, arg3Wired, arg4Wired, arg5Wired);
  2. <font color="#c0c0c0">arg3Wired_dtor(arg3Wired); // std::string
  3. arg4Wired_dtor(arg4Wired); // std::string</font>
  4. 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这个函数的内部。
进去以后发现是这样的:
  1. var dynCall_iiiiiiii = WasmModule["dynCall_iiiiiiii"] = function() {
  2.     return WasmModule["asm"]["Ta"].apply(null, arguments)
  3. }
复制代码
arguments是一个数组,就是上面dynCall(rawFunction, a1, a2, a3, a4, a5, a6, a7)传递进来的8个变量.
同样的,到console里调试执行 “return WasmModule["asm"]["Ta"].apply(null, arguments)”  返回5,并且结果直接返回到了emval_handle_array数组中。


如果你跟进去的话你就会发现是一个死循环,一直在不停死循环,我尝试跟着他,跟了几个小时都跟不到关键算法,一直就在这里来换切换
跟进去以后是这样,再往里面跟就是另外一个和下面这个格式差不多的另外一个函数,反正就是一直循环,始终找不到关键算法。
  1. var stackSave = WasmModule["stackSave"] = function() {
  2.     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。
结帖率:94% (15/16)
 楼主| 发表于 2019-10-18 15:45:53 | 显示全部楼层   四川省巴中市
blackBear 发表于 2019-10-16 11:41
逆向出加密算法?

找到关键的加密算法的代码调用。
回复

使用道具 举报

签到天数: 12 天

发表于 2019-10-16 04:44:00 | 显示全部楼层   陕西省榆林市
我找到了關鍵:

return WasmModule["asm"]["Ta"].apply(null, arguments)
return WasmModule["asm"]["jb"].apply(null, arguments)

別的都沒變,Ta變成了jb。

点评

就是在这2个里面循环,然后结果就出来了,但是追不到具体的生成地方   四川省巴中市  发表于 2019-10-17 21:06
回复

使用道具 举报

结帖率:80% (24/30)
发表于 2019-10-16 10:18:28 | 显示全部楼层   安徽省滁州市
为什么我看到的加密参数只有sign和did。。。。
回复

使用道具 举报

发表于 2019-10-16 11:41:49 | 显示全部楼层   贵州省贵阳市
逆向出加密算法?
回复

使用道具 举报

结帖率:33% (2/6)
发表于 2020-10-20 07:25:53 | 显示全部楼层   浙江省丽水市
算法是不是在flash层的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表