绕过开发者工具限制

绕过网站对开发工具和调试功能的限制,具有增强的保护和性能

目前为 2024-10-31 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name DevTools Bypass
  3. // @name:vi Bỏ Qua Chặn DevTools
  4. // @name:zh-CN 绕过开发者工具限制
  5. // @namespace https://greasyfork.org/vi/users/1195312-renji-yuusei
  6. // @version 2.2
  7. // @description Bypass website restrictions on DevTools and debugging capabilities with enhanced protection and performance
  8. // @description:vi Bỏ qua các hạn chế của trang web về DevTools và khả năng gỡ lỗi với bảo vệ và hiệu suất nâng cao
  9. // @description:zh-CN 绕过网站对开发工具和调试功能的限制,具有增强的保护和性能
  10. // @author Yuusei
  11. // @match *://*/*
  12. // @grant unsafeWindow
  13. // @run-at document-start
  14. // @license GPL-3.0-only
  15. // ==/UserScript==
  16.  
  17. (function () {
  18. 'use strict';
  19.  
  20. const config = {
  21. debugKeywords: /;\s*(?:debugger|debug(?:ger)?|breakpoint)\s*;?/g,
  22. consoleProps: ['log', 'warn', 'error', 'info', 'debug', 'assert', 'dir', 'dirxml', 'trace', 'group', 'groupCollapsed', 'groupEnd', 'time', 'timeEnd', 'profile', 'profileEnd', 'count', 'table', 'clear'],
  23. maxLogHistory: 100,
  24. whitelist: /^(?:example\.com|another-site\.net)$/,
  25. cutoffs: {
  26. table: { amount: 5, within: 5000 },
  27. clear: { amount: 5, within: 5000 },
  28. redactedLog: { amount: 5, within: 5000 },
  29. debugger: { amount: 10, within: 10000 },
  30. debuggerThrow: { amount: 10, within: 10000 },
  31. },
  32. };
  33.  
  34. // Save original methods
  35. const originals = {
  36. console: {},
  37. Function: window.Function.prototype.constructor,
  38. createElement: document.createElement.bind(document),
  39. toString: Function.prototype.toString,
  40. eval: unsafeWindow.eval,
  41. functionConstructor: window.Function,
  42. setInterval: window.setInterval,
  43. addEventListener: window.addEventListener,
  44. };
  45.  
  46. // Save original console methods safely
  47. config.consoleProps.forEach(prop => {
  48. try {
  49. if (console[prop]) {
  50. originals.console[prop] = console[prop].bind(console);
  51. }
  52. } catch (e) {
  53. // Ignore if we can't access the property
  54. }
  55. });
  56.  
  57. const logHistory = [];
  58. let debugCount = 0;
  59.  
  60. // Logging control system with error handling
  61. const shouldLog = type => {
  62. try {
  63. const cutoff = config.cutoffs[type];
  64. if (!cutoff) return true;
  65. if (cutoff.tripped) return false;
  66.  
  67. cutoff.current = cutoff.current || 0;
  68. const now = Date.now();
  69. cutoff.last = cutoff.last || now;
  70.  
  71. if (now - cutoff.last > cutoff.within) {
  72. cutoff.current = 0;
  73. }
  74.  
  75. cutoff.last = now;
  76. cutoff.current++;
  77.  
  78. if (cutoff.current > cutoff.amount) {
  79. originals.console.warn?.(`Limit reached! Will now ignore ${type}`);
  80. cutoff.tripped = true;
  81. return false;
  82. }
  83.  
  84. return true;
  85. } catch (e) {
  86. return true; // Default to allowing logs on error
  87. }
  88. };
  89.  
  90. // Enhanced safe evaluation with better error handling
  91. const safeEval = code => {
  92. try {
  93. const wrapped = `(function() { ${code} })()`;
  94. return Function(wrapped)();
  95. } catch (error) {
  96. originals.console.error?.('Failed to evaluate code:', error);
  97. return null;
  98. }
  99. };
  100.  
  101. // Advanced function modification with improved safety
  102. const modifyFunction = func => {
  103. if (typeof func !== 'function') return func;
  104.  
  105. try {
  106. const funcStr = func.toString();
  107. if (config.debugKeywords.test(funcStr)) {
  108. const modifiedStr = funcStr.replace(config.debugKeywords, ';/* debugger removed */;');
  109. return safeEval(modifiedStr) || func;
  110. }
  111. } catch (e) {
  112. // If modification fails, return original function
  113. }
  114. return func;
  115. };
  116.  
  117. // Enhanced console wrapper with proper prototype handling
  118. const wrapConsole = () => {
  119. const wrappedConsole = {};
  120.  
  121. config.consoleProps.forEach(prop => {
  122. try {
  123. Object.defineProperty(wrappedConsole, prop, {
  124. configurable: true,
  125. enumerable: true,
  126. writable: true,
  127. value: function (...args) {
  128. if (!shouldLog(prop)) return;
  129.  
  130. // Special cases handling
  131. if (prop === 'clear' && shouldLog('clear')) {
  132. originals.console.warn?.('Clear prevented');
  133. return;
  134. }
  135.  
  136. // Process arguments safely
  137. const processedArgs = args.map(arg => {
  138. try {
  139. if (typeof arg === 'function') return '[Function]';
  140. if (!arg || typeof arg !== 'object') return arg;
  141.  
  142. // Check for potential anti-debug objects
  143. if (Object.getOwnPropertyDescriptor(arg, 'toString')) {
  144. return '[Object]';
  145. }
  146.  
  147. return arg;
  148. } catch (e) {
  149. return '[Protected]';
  150. }
  151. });
  152.  
  153. // Apply the original console method if available
  154. if (originals.console[prop]) {
  155. originals.console[prop].apply(console, processedArgs);
  156. }
  157. },
  158. });
  159. } catch (e) {
  160. // Skip if property cannot be wrapped
  161. }
  162. });
  163.  
  164. // Safely replace console methods
  165. try {
  166. Object.defineProperty(window, 'console', {
  167. configurable: true,
  168. enumerable: true,
  169. get: () => wrappedConsole,
  170. });
  171. } catch (e) {
  172. // Fallback: try to copy methods individually
  173. config.consoleProps.forEach(prop => {
  174. try {
  175. console[prop] = wrappedConsole[prop];
  176. } catch (_) {}
  177. });
  178. }
  179. };
  180.  
  181. // Function constructor protection with improved error handling
  182. const protectFunctionConstructor = () => {
  183. try {
  184. const handler = {
  185. apply(target, thisArg, args) {
  186. const modifiedArgs = args.map(arg => (typeof arg === 'string' ? arg.replace(config.debugKeywords, '') : arg));
  187. return Reflect.apply(target, thisArg, modifiedArgs);
  188. },
  189. construct(target, args) {
  190. const modifiedArgs = args.map(arg => (typeof arg === 'string' ? arg.replace(config.debugKeywords, '') : arg));
  191. return Reflect.construct(target, modifiedArgs);
  192. },
  193. };
  194.  
  195. window.Function = new Proxy(window.Function, handler);
  196. } catch (e) {
  197. // Fallback protection if Proxy fails
  198. const originalFunction = window.Function;
  199. window.Function = function (...args) {
  200. const modifiedArgs = args.map(arg => (typeof arg === 'string' ? arg.replace(config.debugKeywords, '') : arg));
  201. return originalFunction.apply(this, modifiedArgs);
  202. };
  203. Object.setPrototypeOf(window.Function, originalFunction);
  204. }
  205. };
  206.  
  207. // Enhanced createElement protection
  208. const protectCreateElement = () => {
  209. try {
  210. document.createElement = new Proxy(originals.createElement, {
  211. apply(target, thisArg, args) {
  212. const element = Reflect.apply(target, thisArg, args);
  213. if (args[0]?.toLowerCase?.() === 'iframe') {
  214. element.addEventListener('load', () => {
  215. try {
  216. const iframeConsole = element.contentWindow.console;
  217. Object.keys(wrappedConsole).forEach(key => {
  218. try {
  219. iframeConsole[key] = wrappedConsole[key];
  220. } catch (_) {}
  221. });
  222. } catch (_) {}
  223. });
  224. }
  225. return element;
  226. },
  227. });
  228. } catch (e) {
  229. // Fallback if Proxy fails
  230. }
  231. };
  232.  
  233. // Main protection setup with improved error handling
  234. const setupProtection = () => {
  235. try {
  236. if (config.whitelist.test(window.location.host)) return;
  237.  
  238. wrapConsole();
  239. protectFunctionConstructor();
  240. protectCreateElement();
  241.  
  242. // Protect video playback
  243. try {
  244. const originalPlay = HTMLMediaElement.prototype.play;
  245. Object.defineProperty(HTMLMediaElement.prototype, 'play', {
  246. configurable: true,
  247. writable: true,
  248. value: function (...args) {
  249. return originalPlay.apply(this, args);
  250. },
  251. });
  252. } catch (_) {}
  253.  
  254. // Initialize protection message
  255. console.log('%cDevTools Bypass is active', 'color: #00ff00; font-weight: bold;');
  256. } catch (e) {
  257. // Silent fail for maximum stealth
  258. }
  259. };
  260.  
  261. // Initialize protection
  262. setupProtection();
  263. })();