开发工具限制绕过

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

当前为 2024-11-01 提交的版本,查看 最新版本

  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.3
  7. // @description Bypass for website restrictions on DevTools with improved protection
  8. // @description:vi Bỏ qua các hạn chế của trang web về DevTools với bảo vệ được cải tiến
  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. cutoffs: {
  25. table: { amount: 10, within: 10000 },
  26. clear: { amount: 10, within: 10000 },
  27. redactedLog: { amount: 10, within: 10000 },
  28. debugger: { amount: 15, within: 15000 },
  29. debuggerThrow: { amount: 15, within: 15000 },
  30. },
  31. protectionLevel: 'aggressive'
  32. };
  33.  
  34. // Originals storage with deep cloning
  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. setTimeout: window.setTimeout,
  44. addEventListener: window.addEventListener,
  45. removeEventListener: window.removeEventListener
  46. };
  47.  
  48. // Console method preservation
  49. config.consoleProps.forEach(prop => {
  50. try {
  51. if (console[prop]) {
  52. originals.console[prop] = console[prop].bind(console);
  53. }
  54. } catch (e) {
  55. // Silent fail for stealth
  56. }
  57. });
  58.  
  59. const logHistory = new Array(config.maxLogHistory);
  60. let debugCount = 0;
  61.  
  62. // Logging control system
  63. const shouldLog = (type) => {
  64. try {
  65. const cutoff = config.cutoffs[type];
  66. if (!cutoff) return true;
  67. if (cutoff.tripped) return false;
  68.  
  69. const now = Date.now();
  70. cutoff.current = (cutoff.current || 0) + 1;
  71. cutoff.last = cutoff.last || now;
  72.  
  73. if (now - cutoff.last > cutoff.within) {
  74. cutoff.current = 1;
  75. cutoff.last = now;
  76. return true;
  77. }
  78.  
  79. if (cutoff.current > cutoff.amount) {
  80. if (config.protectionLevel === 'aggressive') {
  81. originals.console.warn?.(`Rate limit exceeded for ${type}`);
  82. }
  83. cutoff.tripped = true;
  84. return false;
  85. }
  86.  
  87. return true;
  88. } catch (e) {
  89. return true;
  90. }
  91. };
  92.  
  93. // Safe evaluation with context isolation
  94. const safeEval = (code, context = {}) => {
  95. try {
  96. const isolatedFunc = new Function(
  97. ...Object.keys(context),
  98. `return (function() { ${code} })()`
  99. );
  100. return isolatedFunc(...Object.values(context));
  101. } catch (error) {
  102. if (config.protectionLevel === 'aggressive') {
  103. originals.console.error?.('Evaluation failed:', error);
  104. }
  105. return null;
  106. }
  107. };
  108.  
  109. // Function modification system
  110. const modifyFunction = (func) => {
  111. if (typeof func !== 'function') return func;
  112.  
  113. try {
  114. const funcStr = func.toString();
  115. if (config.debugKeywords.test(funcStr)) {
  116. const modifiedStr = funcStr.replace(config.debugKeywords, ';/* debug removed */;');
  117. return safeEval(modifiedStr) || func;
  118. }
  119. } catch (e) {
  120. // Return original on failure
  121. }
  122. return func;
  123. };
  124.  
  125. // Console wrapper with protection
  126. const wrapConsole = () => {
  127. const wrappedConsole = {};
  128.  
  129. config.consoleProps.forEach(prop => {
  130. try {
  131. Object.defineProperty(wrappedConsole, prop, {
  132. configurable: true,
  133. enumerable: true,
  134. writable: true,
  135. value: function(...args) {
  136. if (!shouldLog(prop)) return;
  137.  
  138. if (prop === 'clear' && shouldLog('clear')) {
  139. if (config.protectionLevel === 'aggressive') {
  140. originals.console.warn?.('Console clear prevented');
  141. }
  142. return;
  143. }
  144.  
  145. const processedArgs = args.map(arg => {
  146. try {
  147. if (typeof arg === 'function') return '[Function]';
  148. if (!arg || typeof arg !== 'object') return arg;
  149. const descriptors = Object.getOwnPropertyDescriptor(arg, 'toString');
  150. if (descriptors && !descriptors.configurable) {
  151. return '[Protected Object]';
  152. }
  153.  
  154. return arg;
  155. } catch (e) {
  156. return '[Protected]';
  157. }
  158. });
  159.  
  160. if (originals.console[prop]) {
  161. originals.console[prop].apply(console, processedArgs);
  162. }
  163. }
  164. });
  165. } catch (e) {
  166. // Skip problematic properties
  167. }
  168. });
  169.  
  170. // Console protection with fallback
  171. try {
  172. Object.defineProperty(window, 'console', {
  173. configurable: true,
  174. enumerable: true,
  175. get: () => wrappedConsole
  176. });
  177. } catch (e) {
  178. config.consoleProps.forEach(prop => {
  179. try {
  180. console[prop] = wrappedConsole[prop];
  181. } catch (_) {}
  182. });
  183. }
  184. };
  185.  
  186. // Function constructor protection
  187. const protectFunctionConstructor = () => {
  188. try {
  189. const handler = {
  190. apply(target, thisArg, args) {
  191. const modifiedArgs = args.map(arg =>
  192. typeof arg === 'string' ? arg.replace(config.debugKeywords, '') : arg
  193. );
  194. return Reflect.apply(target, thisArg, modifiedArgs);
  195. },
  196. construct(target, args) {
  197. const modifiedArgs = args.map(arg =>
  198. typeof arg === 'string' ? arg.replace(config.debugKeywords, '') : arg
  199. );
  200. return Reflect.construct(target, modifiedArgs);
  201. }
  202. };
  203.  
  204. window.Function = new Proxy(window.Function, handler);
  205. } catch (e) {
  206. const originalFunction = window.Function;
  207. window.Function = function(...args) {
  208. const modifiedArgs = args.map(arg =>
  209. typeof arg === 'string' ? arg.replace(config.debugKeywords, '') : arg
  210. );
  211. return originalFunction.apply(this, modifiedArgs);
  212. };
  213. Object.setPrototypeOf(window.Function, originalFunction);
  214. }
  215. };
  216.  
  217. // createElement protection
  218. const protectCreateElement = () => {
  219. try {
  220. document.createElement = new Proxy(originals.createElement, {
  221. apply(target, thisArg, args) {
  222. const element = Reflect.apply(target, thisArg, args);
  223. if (args[0]?.toLowerCase?.() === 'iframe') {
  224. const protectIframe = () => {
  225. try {
  226. const iframeWindow = element.contentWindow;
  227. const iframeConsole = iframeWindow.console;
  228. Object.keys(wrappedConsole).forEach(key => {
  229. try {
  230. iframeConsole[key] = wrappedConsole[key];
  231. } catch (_) {}
  232. });
  233.  
  234. // Protect iframe's Function constructor
  235. iframeWindow.Function = window.Function;
  236. } catch (_) {}
  237. };
  238.  
  239. element.addEventListener('load', protectIframe, { once: true });
  240. }
  241. return element;
  242. }
  243. });
  244. } catch (e) {
  245. // Fallback protection
  246. }
  247. };
  248.  
  249. // Timer protection
  250. const protectTimers = () => {
  251. try {
  252. const wrapTimer = (original, name) => {
  253. return function(handler, ...args) {
  254. if (typeof handler === 'string') {
  255. handler = handler.replace(config.debugKeywords, '');
  256. } else if (typeof handler === 'function') {
  257. handler = modifyFunction(handler);
  258. }
  259. return original.call(this, handler, ...args);
  260. };
  261. };
  262.  
  263. window.setInterval = wrapTimer(originals.setInterval, 'setInterval');
  264. window.setTimeout = wrapTimer(originals.setTimeout, 'setTimeout');
  265. } catch (e) {
  266. // Fallback to originals
  267. }
  268. };
  269.  
  270. // Main protection setup with improved error handling
  271. const setupProtection = () => {
  272. try {
  273. wrapConsole();
  274. protectFunctionConstructor();
  275. protectCreateElement();
  276. protectTimers();
  277.  
  278. // Media protection
  279. try {
  280. const mediaProto = HTMLMediaElement.prototype;
  281. const originalPlay = mediaProto.play;
  282. Object.defineProperty(mediaProto, 'play', {
  283. configurable: true,
  284. writable: true,
  285. value: function(...args) {
  286. return originalPlay.apply(this, args);
  287. }
  288. });
  289. } catch (_) {}
  290.  
  291. // Success message
  292. if (config.protectionLevel === 'aggressive') {
  293. console.log('%cDevTools Bypass activated', 'color: #00ff00; font-weight: bold;');
  294. }
  295. } catch (e) {
  296. // Silent fail for stealth
  297. }
  298. };
  299.  
  300. // Initialize protection
  301. setupProtection();
  302. })();