李恒道 发表于 2022-3-5 03:07:36

超级星星videojs劫持分析

# 前言

予以自乐,好求知,不求甚解

# 开始

之前是对window.videojs进行劫持初始化函数,我们发现这次无法重新赋值

使用描述符读取函数发现可写为了flase

这是我们有两种方式

1.对其object.definproperty进行劫持,设置writable为true

然后继续进行劫持

2.对videojs进行核心劫持

第一种方案为

```js
+if(unsafeWindow.location.href.indexOf('/modules/video')!==-1){
+    let fuck=Object.defineProperty
+    Object.defineProperty=function(...args){
+      if(args.length>=2){
+            if(args==='videojs'&&args!==undefined){
+                args.writable=true

+            }
+      }
+      return fuck.call(this,...args)
+    }
```

直接对其进行过滤即可

第二种访问

我们需要阅读videojs源码

https://unpkg.com/video.js@7.17.0/dist/video.js

查看代码

```js
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojs = factory());
}(this, (function () { 'use strict';
```

umd格式,直接拖底部

```js
    return videojs;
```

发现传出一个函数,我们查找videojs

是一个

```js
   function videojs(id, options, ready)
```

大致阅读代码

```js
      var player = videojs.getPlayer(id);

      if (player) {
      if (options) {
          log$1.warn("Player \"" + id + "\" is already initialised. Options will not be applied.");
      }

      if (ready) {
          player.ready(ready);
      }

      return player;
      }
```

首先获取id,判断是否存在,如果存在则不初始化

这里我一开始试图对Getplayer进行劫持

后来发现少参,放弃

```js
      var el = typeof id === 'string' ? $('#' + normalizeId(id)) : id;

      if (!isEl(el)) {
      throw new TypeError('The element or ID supplied is not valid. (videojs)');
      } // document.body.contains(el) will only check if el is contained within that one document.
      // This causes problems for elements in iframes.
      // Instead, use the element's ownerDocument instead of the global document.
      // This will make sure that the element is indeed in the dom of that document.
      // Additionally, check that the document in question has a default view.
      // If the document is no longer attached to the dom, the defaultView of the document will be null.


      if (!el.ownerDocument.defaultView || !el.ownerDocument.body.contains(el)) {
      log$1.warn('The element supplied is not included in the DOM');
      }

      options = options || {};
      hooks('beforesetup').forEach(function (hookFunction) {
      var opts = hookFunction(el, mergeOptions$3(options));

      if (!isObject$1(opts) || Array.isArray(opts)) {
          log$1.error('please return an object in beforesetup hooks');
          return;
      }

      options = mergeOptions$3(options, opts);
      }); // We get the current "Player" component here in case an integration has
      // replaced it with a custom player.
```

兼容化处理+options合并,跳过

```js
      var PlayerComponent = Component$1.getComponent('Player');
      player = new PlayerComponent(el, options, ready);
      hooks('setup').forEach(function (hookFunction) {
      return hookFunction(player);
      });
      return player;
```

这里发现通过了Component.GetComponent读了Player函数

然后对其构造,最后调用了Hooks回调钩,传入了一个函数,然后循环遍历

等等,嗯?

hooks钩?

往前翻

```js
      hooks('beforesetup').forEach(function (hookFunction) {
      var opts = hookFunction(el, mergeOptions$3(options));

      if (!isObject$1(opts) || Array.isArray(opts)) {
          log$1.error('please return an object in beforesetup hooks');
          return;
      }

      options = mergeOptions$3(options, opts);
      });
```

```js
      hooks('setup').forEach(function (hookFunction) {
      return hookFunction(player);
      });
```

经典的beforeCreated钩和Created钩

查询参数手册

https://docs.videojs.com/tutorial-hooks.html

```js
videojs.hook('beforesetup', function(videoEl, options) {

// videoEl will be the video element with id="some-id" since that
// gets passed to videojs() below. On subsequent calls, it will be
// different.

videoEl.className += ' some-super-class';

// autoplay will be true here, since we passed it as such.
if (options.autoplay) {
    options.autoplay = false
}

// Options that are returned here will be merged with old options.
//
// In this example options will now be:
//   {autoplay: false, controls: true}
//
// This has the practical effect of always disabling autoplay no matter
// what options are passed to videojs().
return options;
});
```

```js
videojs.hook('setup', function(player) {

// Initialize the foo plugin after any player is created.
player.foo();
});
```

````js
beforesetup
beforesetup occurs just before a player is created. This allows:

Modification of the options passed to the Video.js function (e.g., videojs('some-id, options)).
Modification of the DOM video element that will be used for the player that will be created.
beforesetup hook functions should:

Take two arguments:
videoEl: DOM <video> element that Video.js is going to use to create a player.
options: The options object that Video.js was called with and will be passed to the player during creation.
Return an options object that will be merged with the originally provided options.
```
````

```js
setup
setup occurs just after a player is created. This allows:

Plugins or other custom functionality to initialize on the player.
Changes to the player object itself.
setup hook functions:

Take one argument:
player: the player that Video.js created
Don't have to return anything
```

大概意思就不翻译了

有兴趣谷歌翻译一下

直接秒就完了

# 结语

社会摇中万人迷,唯有道总着人迷

社会摇中没有将与帅,只有实力这一块

李恒道 发表于 2022-3-5 03:08:16

yy550623346 发表于 2022-3-5 08:52:25

沙发,顶起,多谢大佬

yy550623346 发表于 2022-3-5 09:14:23

function hookVideo() {
    _self.alert = console.log;
    var config = arguments;
    if (!config) {
      return vjs.apply(this, arguments);
    }
    var line = Ext.Array.filter(Ext.Array.map(config.playlines, function (value, index) {
      return value.label == setting.line && index;
    }), function (value) {
      return Ext.isNumber(value);
    }) || 0,
      http = Ext.Array.filter(config.sources, function (value) {
            return value.label == setting.http;
      });
    config.playlines.unshift(config.playlines);
    config.playlines.splice(line + 1, 1);
    config.plugins.videoJsResolutionSwitcher.default = http ? http.res : 360;
    config.plugins.studyControl.enableSwitchWindow = 1;
    config.plugins.timelineObjects.url = '/richvideo/initdatawithviewer?';
    config.plugins.seekBarControl.enableFastForward = 1;
    if (!setting.queue) delete config.plugins.studyControl;
    // config.preload = setting.tip ? 'auto' : 'none';
    var player = vjs.apply(this, arguments),
      a = '<a href="https://d0.ananas.chaoxing.com/download/' + _self.config('objectid') + '" target="_blank">',
      img = '<img src="https://d0.ananas.chaoxing.com/download/e363b256c0e9bc5bd8266bf99dd6d6bb" style="margin: 6px 0 0 6px;">';
    player.volume(Math.round(setting.vol) / 100 || 0);
    Ext.get(player.controlBar.addChild('Button').el_).setHTML(a + img + '</a>').dom.title = '下载视频';
    player.on('loadstart', function () {
      setting.tip && this.play().catch(Ext.emptyFn);
      this.playbackRate(setting.rate > 16 || setting.rate < 0.0625 ? 1 : setting.rate);
    });
    player.one(['loadedmetadata', 'firstplay'], function () {
      setting.two = setting.rate === '0' && setting.two < 1;
      setting.two && config.plugins.seekBarControl.sendLog(this.children_, 'ended', Math.floor(this.cache_.duration));
    });
    player.on('ended', function () {
      Ext.fly(frameElement).parent().addCls('ans-job-finished');
    });
    return player;
}
那这段怎么改下呢

Ne-21 发表于 2022-3-5 09:21:23

社会摇中万人迷,唯有道总着人迷

李恒道 发表于 2022-3-5 13:35:09

yy550623346 发表于 2022-3-5 08:52
沙发,顶起,多谢大佬

已经更新了

cocang 发表于 2022-3-5 21:37:56

绊倒我的人、我们让他永远起不来
扶起我的人、我们让他永远不会摔倒
页: [1]
查看完整版本: 超级星星videojs劫持分析