您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
解锁复制/粘贴/右键,彻底屏蔽 debugger 循环和 eval/Function 注入。
// ==UserScript== // @name 网站限制解除脚本 // @namespace https://web.zyxn.dpdns.org // @version 4.0 // @description 解锁复制/粘贴/右键,彻底屏蔽 debugger 循环和 eval/Function 注入。 // @author flkGit // @match *://*/* // @run-at document-start // @grant none // @license MIT // ==/UserScript== (function(){ 'use strict'; // --- 基础解锁:右键/复制/粘贴 + F12保护 --- const SENSITIVE_EVENTS = [ 'copy', 'paste', 'cut', 'contextmenu', 'selectstart', 'dragstart', 'keydown', 'keyup', 'keypress' // 包含键盘事件保护F12等 ]; // 高优先级事件拦截 for (const ev of SENSITIVE_EVENTS) { window.addEventListener(ev, e => { // 特殊保护开发者工具快捷键 if (e.type.startsWith('key')) { const isF12 = e.keyCode === 123; const isDevTools = e.ctrlKey && e.shiftKey && e.keyCode === 73; // Ctrl+Shift+I const isConsole = e.ctrlKey && e.shiftKey && e.keyCode === 74; // Ctrl+Shift+J const isViewSource = e.ctrlKey && e.keyCode === 85; // Ctrl+U const isInspect = e.ctrlKey && e.shiftKey && e.keyCode === 67; // Ctrl+Shift+C if (isF12 || isDevTools || isConsole || isViewSource || isInspect) { e.stopImmediatePropagation(); return; // 让浏览器处理这些快捷键 } } // 其他敏感事件全部放行 e.stopImmediatePropagation(); }, true); } // 清理内联事件处理器 function cleanInline() { const inlineEvents = ['oncopy', 'onpaste', 'oncut', 'oncontextmenu', 'onselectstart', 'onkeydown', 'onkeyup']; const targets = [document, document.documentElement, document.body].filter(Boolean); for (const target of targets) { for (const attr of inlineEvents) { if (target[attr]) target[attr] = null; } } } // 定期清理 + 页面变化时清理 const cleanTimer = setInterval(cleanInline, 2000); if (typeof MutationObserver !== 'undefined') { new MutationObserver(cleanInline).observe(document, {childList: true, subtree: true}); } // 页面卸载前清理定时器 window.addEventListener('beforeunload', () => clearInterval(cleanTimer)); // 强制CSS样式解锁 function injectUnlockCSS() { if (document.head) { const style = document.createElement('style'); style.textContent = ` * { -webkit-user-select: text !important; -moz-user-select: text !important; user-select: text !important; -webkit-touch-callout: default !important; -webkit-user-drag: element !important; pointer-events: auto !important; } `; document.head.appendChild(style); } } // 立即注入CSS,DOM加载后再次注入 injectUnlockCSS(); document.addEventListener('DOMContentLoaded', injectUnlockCSS); // 强制允许 execCommand const origExecCommand = document.execCommand; document.execCommand = function(cmd, showUI, value) { return origExecCommand.call(this, cmd, showUI, value) || true; // 强制返回true }; // === 增强版 Debugger 拦截系统 === function createDebuggerBlocker() { const logBlocked = (type, info) => console.warn(`[Debugger Blocked] ${type}:`, info); // 1. 重写核心函数 const originals = { eval: window.eval, Function: window.Function, setTimeout: window.setTimeout, setInterval: window.setInterval }; // 检测debugger的正则(更严格) const debuggerRegex = /\bdebugger\b/; // 重写 eval window.eval = function(code) { if (typeof code === 'string' && debuggerRegex.test(code)) { logBlocked('eval', code.slice(0, 100)); return undefined; } return originals.eval.call(this, code); }; // 重写 Function 构造器 window.Function = function(...args) { const code = args[args.length - 1]; if (typeof code === 'string' && debuggerRegex.test(code)) { logBlocked('Function', code.slice(0, 100)); return () => {}; // 返回无害的空函数 } return originals.Function.apply(this, args); }; // 重写定时器函数 const wrapTimer = (original, name) => function(callback, delay, ...args) { if (typeof callback === 'string' && debuggerRegex.test(callback)) { logBlocked(name + ' string', callback.slice(0, 100)); return original.call(this, () => {}, delay, ...args); } if (typeof callback === 'function') { try { const funcStr = callback.toString(); if (debuggerRegex.test(funcStr)) { logBlocked(name + ' function', funcStr.slice(0, 100)); return original.call(this, () => {}, delay, ...args); } } catch (e) { // 如果toString()失败,可能是native函数,放行 } } return original.call(this, callback, delay, ...args); }; window.setTimeout = wrapTimer(originals.setTimeout, 'setTimeout'); window.setInterval = wrapTimer(originals.setInterval, 'setInterval'); // 2. 主动清理现有定时器 let cleanupActive = true; const cleanupDebuggers = () => { if (!cleanupActive) return; try { // 获取当前最高的timer ID const testId = setTimeout(() => {}, 0); clearTimeout(testId); // 清理可疑的定时器(延迟很短的) for (let i = Math.max(1, testId - 1000); i <= testId; i++) { try { clearTimeout(i); clearInterval(i); } catch (e) {} } } catch (e) {} }; // 启动清理任务 const cleanupTimer = setInterval(cleanupDebuggers, 3000); // 15秒后停止清理 setTimeout(() => { cleanupActive = false; clearInterval(cleanupTimer); logBlocked('cleanup', '定时器清理任务已完成'); }, 15000); // 3. 保护 console 对象 try { const originalClear = console.clear; Object.defineProperty(console, 'clear', { value: function() { logBlocked('console.clear', '阻止清除控制台'); }, writable: false, configurable: false }); } catch (e) {} } // 立即启动debugger拦截 createDebuggerBlocker(); // === 页面加载完成后的额外保护 === const finalSetup = () => { cleanInline(); injectUnlockCSS(); // 移除可能的CSS限制 const restrictiveStyles = document.querySelectorAll('style, link[rel="stylesheet"]'); restrictiveStyles.forEach(style => { try { if (style.textContent && /user-select\s*:\s*none|pointer-events\s*:\s*none/.test(style.textContent)) { style.textContent = style.textContent .replace(/user-select\s*:\s*none/gi, 'user-select: text') .replace(/pointer-events\s*:\s*none/gi, 'pointer-events: auto'); } } catch (e) {} }); }; // 多个时机执行最终设置 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', finalSetup); } else { finalSetup(); } window.addEventListener('load', () => setTimeout(finalSetup, 500)); console.info('[Unlocker v4.0] 已启用:F12保护 + 复制解锁 + Debugger全面拦截'); })();