Bypass DevTools Detection

Prevent websites from detecting DevTools (Inspect Element) is open

目前為 2025-06-02 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Bypass DevTools Detection
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Prevent websites from detecting DevTools (Inspect Element) is open
  6. // @author Serial Desegnation J
  7. // @match *://*/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. // --- Override debugger to noop ---
  15. window.debugger = function() {};
  16.  
  17. // Spoof Function.prototype.constructor to strip debugger statements from strings
  18. const originalConstructor = Function.prototype.constructor;
  19. Function.prototype.constructor = new Proxy(originalConstructor, {
  20. apply(target, thisArg, args) {
  21. if (args[0] && typeof args[0] === 'string' && args[0].includes('debugger')) {
  22. args[0] = args[0].replace(/debugger/g, '');
  23. }
  24. return Reflect.apply(target, thisArg, args);
  25. }
  26. });
  27.  
  28. // Spoof Function.prototype.toString to hide overrides (especially debugger function)
  29. const originalToString = Function.prototype.toString;
  30. Function.prototype.toString = new Proxy(originalToString, {
  31. apply(target, thisArg, args) {
  32. if (thisArg === window.debugger) {
  33. return 'function debugger() { [native code] }';
  34. }
  35. return Reflect.apply(target, thisArg, args);
  36. }
  37. });
  38.  
  39. // Override eval to strip debugger statements from any eval'd code
  40. const originalEval = window.eval;
  41. window.eval = function(code) {
  42. if (typeof code === 'string') {
  43. code = code.replace(/debugger;?/g, '');
  44. }
  45. return originalEval(code);
  46. };
  47.  
  48. // Override console methods to disable traps and weird behaviors
  49. ['log', 'debug', 'error', 'info', 'warn'].forEach(method => {
  50. const originalMethod = console[method];
  51. console[method] = function(...args) {
  52. // Skip logging if args include certain trap images or weird data (optional)
  53. for (const arg of args) {
  54. if (arg instanceof Image) return;
  55. }
  56. return originalMethod.apply(console, args);
  57. };
  58. });
  59.  
  60. // Block console.clear to prevent wiping logs
  61. console.clear = function () {
  62. console.log('[Tampermonkey] Blocked console.clear()');
  63. };
  64.  
  65. // Spoof window.outerWidth and outerHeight to match inner dimensions (for devtools detection)
  66. function spoofWindowSize() {
  67. Object.defineProperty(window, 'outerWidth', {
  68. get: () => window.innerWidth,
  69. configurable: true
  70. });
  71. Object.defineProperty(window, 'outerHeight', {
  72. get: () => window.innerHeight,
  73. configurable: true
  74. });
  75. }
  76. spoofWindowSize();
  77. // Repeat periodically to counter site attempts to redefine
  78. setInterval(spoofWindowSize, 1000);
  79.  
  80. // Override requestAnimationFrame to fudge timestamps (blocks timing detection)
  81. const originalRAF = window.requestAnimationFrame;
  82. window.requestAnimationFrame = function(callback) {
  83. return originalRAF(function(time) {
  84. callback(time + 1000);
  85. });
  86. };
  87.  
  88. // Prevent key combos that open DevTools or View Source
  89. document.addEventListener('keydown', function(e) {
  90. if (
  91. e.key === 'F12' ||
  92. (e.ctrlKey && e.shiftKey && ['I', 'J', 'C'].includes(e.key.toUpperCase())) ||
  93. (e.ctrlKey && e.key.toUpperCase() === 'U')
  94. ) {
  95. e.stopImmediatePropagation();
  96. e.preventDefault();
  97. }
  98. }, true);
  99.  
  100. // Prevent detection via image get traps (used in object inspection)
  101. const imageProto = Object.getPrototypeOf(new Image());
  102. if (imageProto) {
  103. Object.defineProperty(imageProto, 'id', {
  104. get: function() {
  105. return null;
  106. },
  107. configurable: true
  108. });
  109. }
  110.  
  111. // Spoof performance navigation type to hide reload detection
  112. try {
  113. if (performance.getEntriesByType("navigation")[0].type === "reload") {
  114. Object.defineProperty(performance, 'getEntriesByType', {
  115. value: () => [{ type: "navigate" }],
  116. configurable: true
  117. });
  118. }
  119. } catch (e) {}
  120.  
  121. // Spoof navigator.plugins and navigator.languages to look real
  122. Object.defineProperty(navigator, 'plugins', {
  123. get: () => [1, 2, 3],
  124. configurable: true
  125. });
  126. Object.defineProperty(navigator, 'languages', {
  127. get: () => ['en-US', 'en'],
  128. configurable: true
  129. });
  130.  
  131. // Spoof HTMLElement.prototype.toString to prevent element inspection detection
  132. const originalGetOwnPropDesc = Object.getOwnPropertyDescriptor;
  133. Object.getOwnPropertyDescriptor = new Proxy(originalGetOwnPropDesc, {
  134. apply(target, thisArg, args) {
  135. if (args[0] === HTMLElement.prototype && args[1] === 'toString') {
  136. return {
  137. configurable: true,
  138. enumerable: false,
  139. value: () => '[object HTMLElement]'
  140. };
  141. }
  142. return Reflect.apply(target, thisArg, args);
  143. }
  144. });
  145.  
  146. // Debugging confirmation message
  147. console.log('[Tampermonkey] DevTools detection blocked (enhanced).');
  148.  
  149. })();

QingJ © 2025

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