中国大学MOOC反检测

防止中国大学MOOC页面检测模拟点击类插件/脚本(目前已发现的检测只有检测模拟点击类的)

目前为 2022-06-04 提交的版本。查看 最新版本

  1. /* eslint-disable no-multi-spaces */
  2.  
  3. // ==UserScript==
  4. // @name 中国大学MOOC反检测
  5. // @name:zh-CN 中国大学MOOC反检测
  6. // @name:en iCourse163 Anti-detect
  7. // @namespace iCourse163-Anti-detect
  8. // @version 0.1
  9. // @description 防止中国大学MOOC页面检测模拟点击类插件/脚本(目前已发现的检测只有检测模拟点击类的)
  10. // @description:zh-CN 防止中国大学MOOC页面检测模拟点击类插件/脚本(目前已发现的检测只有检测模拟点击类的)
  11. // @description:en Prevent plugins(e.g. userscripts) being detected by 1course163 while simulating clicks on webpage
  12. // @author PY-DNG
  13. // @license WTFPL - See https://www.wtfpl.net/
  14. // @match http*://www.icourse163.org/*
  15. // @icon https://pic.jitudisk.com/public/2022/06/04/59e467b286dcb.png
  16. // @grant none
  17. // @run-at document-start
  18. // ==/UserScript==
  19.  
  20. /**
  21. * Copyright © 2022 PY-DNG <NO EMAIL HERE>
  22. * This work is free. You can redistribute it and/or modify it under the
  23. * terms of the Do What The Fuck You Want To Public License, Version 2,
  24. * as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
  25. **/
  26.  
  27. /**
  28. * This program is free software. It comes without any warranty, to
  29. * the extent permitted by applicable law. You can redistribute it
  30. * and/or modify it under the terms of the Do What The Fuck You Want
  31. * To Public License, Version 2, as published by Sam Hocevar. See
  32. * http://www.wtfpl.net/ for more details.
  33. **/
  34.  
  35. (function(window, document) {
  36. /* Protect.js by PY-DNG */
  37. /* !IMPORTANT! MAKE SURE THIS CODE IS EXECUTED BEFORE WINDOW ONLOAD !IMPORTANT! */
  38.  
  39. try {
  40. // Unpolluted resources
  41. const iframe = document.createElement('iframe');
  42. iframe.srcdoc = '<html></html>';
  43. iframe.style.position = 'fixed';
  44. iframe.style.width = iframe.style.height = '0';
  45. (document.body ? document.body : document.head).appendChild(iframe);
  46. const UNPOLLUTED = new Proxy({}, {
  47. get: function(target, property, receiver) {
  48. switch (property) {
  49. case 'iframe': return iframe;
  50. default: {
  51. let value = iframe;
  52. for (const prop of property.split(/[\.\/]/)) {
  53. value = value[prop];
  54. }
  55. return value;
  56. }
  57. }
  58. }
  59. });
  60.  
  61. // Protect addEventListener & removeEventListener
  62. defineProperty(Node.prototype, 'addEventListener', addEventListener);
  63. defineProperty(Node.prototype, 'removeEventListener', UNPOLLUTED['contentWindow.EventTarget.prototype.removeEventListener']);
  64. for (const func of ['createElement', 'createElementNS', 'querySelector', 'querySelectorAll', 'getElementById', 'getElementsByClassName', 'getElementsByName', 'getElementsByTagName', 'getElementsByTagNameNS']) {
  65. hookAPIFunc(func);
  66. }
  67.  
  68. // Protect root & root-like elements
  69. for (const elm of [document.querySelector('#g-body'), document.documentElement, document, window]) {
  70. const addEventListener = UNPOLLUTED['contentWindow.EventTarget.prototype.addEventListener'];
  71. typeof elm === 'object' && elm !== null && hookElm(elm);
  72. }
  73.  
  74. function hookAPIFunc(funcName) {
  75. for (const api of ['Document', 'Element']) {
  76. const API = window[api];
  77. const proto = API.prototype;
  78. proto.hasOwnProperty(funcName) && defineProperty(proto, funcName, function() {
  79. let value = UNPOLLUTED['contentWindow.'+api+'.prototype.'+funcName].apply(this, Array.from(arguments));
  80.  
  81. if (value instanceof NodeList) {
  82. value = Array.prototype.map.call(value, (elm) => (hookElm(elm)));
  83. value.item = (i) => (i < value.length ? value[i] : null);
  84. } else if (value instanceof EventTarget) {
  85. value = hookElm(value);
  86. }
  87. return value;
  88. });
  89. }
  90. }
  91.  
  92. function hookElm(elm) {
  93. defineProperty(elm, 'addEventListener', addEventListener);
  94. defineProperty(elm, 'removeEventListener', UNPOLLUTED['contentWindow.EventTarget.prototype.removeEventListener']);
  95. return elm;
  96. }
  97.  
  98. function defineProperty(obj, prop, value) {
  99. // Check repeat
  100. if (obj._protected && obj._protected[prop] && obj[prop].toString() === value.toString()) {
  101. return false;
  102. }
  103.  
  104. // Define property
  105. define(obj, prop, value, true);
  106.  
  107. // Prevent repeat
  108. !obj._protected && define(obj, '_protected', {}, false);
  109. define(obj._protected, prop, true, true);
  110.  
  111. return true;
  112.  
  113. function define(obj, prop, value, enumerable) {
  114. Object.defineProperty(obj, prop, {
  115. value: value,
  116. writable: false,
  117. configurable: false,
  118. enumerable: enumerable
  119. });
  120. }
  121. }
  122.  
  123. function addEventListener(type, listener) {
  124. const banlist = ['function(a5){if(', 'function(a6){a6'];
  125. for (const bancode of banlist) {
  126. if (type === 'click' && listener.toString().startsWith(bancode)) {
  127. return;
  128. }
  129. }
  130. return UNPOLLUTED['contentWindow.EventTarget.prototype.addEventListener'].apply(this, Array.from(arguments));
  131. }
  132.  
  133. function toString(o) {
  134. return UNPOLLUTED['contentWindow.Object.prototype.toString'].call(o);
  135. }
  136. } catch (err) {
  137. throw err;
  138. debugger;
  139. }
  140. }).apply(null, typeof unsafeWindow === 'object' ? [unsafeWindow, unsafeWindow.document] : [window, document]);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址