第一种:
javascript
// 恢复被网站禁用的 console 方法
(function() {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
const nativeConsole = iframe.contentWindow.console;
['log', 'warn', 'error', 'info', 'debug', 'dir', 'table', 'trace',
'group', 'groupEnd', 'groupCollapsed', 'clear', 'count', 'assert',
'time', 'timeEnd', 'timeLog'].forEach(method => {
if (nativeConsole[method]) {
console[method] = nativeConsole[method].bind(nativeConsole);
}
});
document.body.removeChild(iframe);
console.log('Console 方法已恢复!');
})();
第二种:
javascript
// 恢复被 aes.util.js 禁用的 console 方法
(function() {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
var nc = iframe.contentWindow.console;
// 直接替换整个 window.console
try {
Object.defineProperty(window, 'console', {
value: {
log: nc.log.bind(nc),
warn: nc.warn.bind(nc),
error: nc.error.bind(nc),
info: nc.info.bind(nc),
debug: nc.debug.bind(nc),
dir: nc.dir.bind(nc),
table: nc.table.bind(nc),
trace: nc.trace.bind(nc),
group: nc.group.bind(nc),
groupEnd: nc.groupEnd.bind(nc),
clear: nc.clear.bind(nc),
count: nc.count.bind(nc),
assert: nc.assert.bind(nc),
time: nc.time.bind(nc),
timeEnd: nc.timeEnd.bind(nc)
},
writable: false,
configurable: false
});
console.log('%c Console 已恢复!', 'color: green; font-weight: bold;');
} catch(e) {
console.error('恢复失败:', e);
}
document.body.removeChild(iframe);
})();
第三种:
javascript
// 备用方案:直接使用 iframe 的 console
(function() {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.id = 'console-restore-iframe';
document.body.appendChild(iframe);
// 将 iframe 的 console 暴露为全局变量
window.c = iframe.contentWindow.console;
console.log = window.c.log.bind(window.c);
console.warn = window.c.warn.bind(window.c);
console.error = window.c.error.bind(window.c);
console.info = window.c.info.bind(window.c);
window.c.log('%c 使用 window.c.log() 或 console.log() 打印日志', 'color: green');
})();
第四种:
javascript
/**
* 恢复被网站禁用的 console 方法
* 兼容各种反调试场景:简单重写、Object.defineProperty 锁定、持续监控重写等
*/
(function restoreConsole() {
// 创建隐藏的 iframe 获取原生 console
var iframe = document.createElement('iframe');
iframe.style.cssText = 'display:none!important;width:0;height:0;border:0;';
iframe.id = '__console_restore_iframe__';
// 移除可能存在的旧 iframe
var oldIframe = document.getElementById('__console_restore_iframe__');
if (oldIframe) oldIframe.remove();
document.body.appendChild(iframe);
var nativeConsole = iframe.contentWindow.console;
// 要恢复的方法列表
var methods = ['log', 'warn', 'error', 'info', 'debug', 'dir', 'table',
'trace', 'group', 'groupEnd', 'groupCollapsed', 'clear',
'count', 'assert', 'time', 'timeEnd', 'timeLog'];
// 构建新的 console 对象
var newConsole = {};
methods.forEach(function(method) {
if (nativeConsole[method]) {
newConsole[method] = nativeConsole[method].bind(nativeConsole);
}
});
// 尝试方式二:替换整个 window.console
try {
Object.defineProperty(window, 'console', {
value: newConsole,
writable: false,
configurable: false
});
} catch(e) {
// 方式二失败,尝试方式一:逐个替换方法
methods.forEach(function(method) {
try {
Object.defineProperty(console, method, {
value: newConsole[method],
writable: false,
configurable: false
});
} catch(e2) {
// Object.defineProperty 失败,直接赋值
try {
console[method] = newConsole[method];
} catch(e3) {}
}
});
}
// 暴露备用接口 window.c(方式三的保底方案)
window.c = nativeConsole;
// 注意:不删除 iframe,保持 nativeConsole 存活
// 如果介意 DOM 中有隐藏 iframe,可以取消下面的注释,但可能导致某些情况失效
// document.body.removeChild(iframe);
// 验证并提示
console.log('%c[Console Restored] ', 'color:#0a0;font-weight:bold',
'console 已恢复! 备用方案: window.c.log()');
})();
第五种,简化版(日常使用)覆盖了 99% 的场景,记住这一个就够了
javascript
// 万能恢复 console 脚本
(function(){
var f = document.createElement('iframe');
f.style.display = 'none';
document.body.appendChild(f);
var nc = f.contentWindow.console;
['log','warn','error','info','debug'].forEach(function(m){
try { console[m] = nc[m].bind(nc); } catch(e){}
});
window.c = nc; // 保底方案
console.log('Console 已恢复! 备用: window.c.log()');
})();
油猴脚本:
javascript
// ==UserScript==
// @name 恢复 Console (防重写版)
// @namespace http://tampermonkey.net/
// @version 2.0
// @description 恢复被网站禁用的 console.log,并防止被再次重写
// @match https://www.birdreport.cn/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
// 保存原生 console 引用
var nativeConsole = console;
// 创建 iframe 获取干净的 console
var getCleanConsole = function() {
var f = document.createElement('iframe');
f.style.display = 'none';
(document.body || document.documentElement).appendChild(f);
var c = f.contentWindow.console;
return c;
};
// 页面加载完成后执行保护
var protect = function() {
var nc = getCleanConsole();
// 创建不可修改的 console 对象
var protectedConsole = {};
['log','warn','error','info','debug','dir','table','trace','group','groupEnd','clear','count','assert','time','timeEnd'].forEach(function(m) {
if (nc[m]) {
Object.defineProperty(protectedConsole, m, {
value: nc[m].bind(nc),
writable: false,
configurable: false
});
}
});
// 锁定 window.console
try {
Object.defineProperty(window, 'console', {
value: protectedConsole,
writable: false,
configurable: false
});
} catch(e) {
// 备用方案
window.c = nc;
}
// 同时暴露 window.c 作为保底
window.c = nc;
console.log('%c[Console Protected]', 'color:green;font-weight:bold', 'console 已恢复并锁定!');
};
// DOM 准备好后执行
if (document.body) {
protect();
} else {
document.addEventListener('DOMContentLoaded', protect);
}
// 延迟再执行一次,确保在网站脚本之后
setTimeout(protect, 1000);
setTimeout(protect, 3000);
})();