文章总结: 本文深入讲解JS反调试技术与绕过方法,介绍了无限Debugger、键盘监听、浏览器尺寸检测、console.log特性利用、代码运行时间差等五种常见反调试手段,并提供了禁用断点、条件断点、文件替换、抓包工具修改响应、油猴脚本Hook等实用绕过技巧。文章结构清晰、示例代码完整,适合前端逆向学习参考。 综合评分: 87 文章分类: 逆向分析,WEB安全,代码审计,实战经验
第90天-JS逆向终极对决:当“反调试”遇上“反反调试”
原创
Сяо Яо Сяо Яо
AlphaNet
2026年3月16日 11:09 韩国
朋友们好!你是否曾想一探某个网站背后神奇的JS代码,却一打开开发者工具(F12)就发现页面崩溃或陷入无限循环?🤔 恭喜你,你很可能遇到了传说中的“反调试”技术!
这就像是网站开发者在你和他的代码之间设置了一道道“机关”和“陷阱”,阻止我们这些好奇的探索者窥探其核心逻辑。但正所谓“道高一尺,魔高一丈”,有“反调试”的盾,就有“反反调试”的矛。今天,就让我们一起揭开这层神秘的面纱,深入探索JS反调试的常见招数,并学习如何优雅地绕过它们!
🧐 是什么:JS反调试大揭秘
简单来说,JS反调试 (Anti-Debugging) 是一种开发者用来保护其客户端代码的技术手段。它的核心目的就是检测用户是否打开了浏览器的开发者工具(如Chrome DevTools),一旦发现,就执行一系列干扰操作,让你无法正常进行代码调试和动态分析。
这就像给自己的代码加上了一套“防盗系统”,有效提升了逆向分析的门槛。
🔍 为什么:五花八门的检测手段
开发者们为了实现反调试,可谓是脑洞大开。他们通过各种巧妙的方式来判断你的“调试意图”。以下是一些最常见的检测“机关”:
1. ♾️ 无限Debugger技术
这是最简单粗暴的一招。通过 setInterval 定时器,代码会不停地执行 debugger 语句,让你始终卡在断点处,无法进行下一步操作。
// 无限debugger,让你的调试器“原地罚站”
setInterval(function() {
debugger;
}, 1000);
2. ⌨️ 键盘监听 (F12 / Ctrl+Shift+I)
网页可以直接监听用户的键盘事件。当你按下 F12、Ctrl+Shift+I 等快捷键试图打开开发者工具时,就会触发预设的脚本,比如关闭页面或跳转到其他地方。
// 监听键盘,精准打击F12
window.addEventListener('keydown', function(event) {
if (event.key === 'F12' || (event.ctrlKey && event.shiftKey && event.key === 'I')) {
console.log('检测到非法操作!');
// 在这里可以执行关闭页面、跳转等操作
// window.close();
event.preventDefault(); // 阻止默认行为
}
});
3. 📏 浏览器尺寸检测
一个非常聪明的技巧!当开发者工具打开时(特别是停靠在窗口侧边或底部时),网页的可视区域尺寸会发生变化。通过检测 window.outerWidth - window.innerWidth 或 window.outerHeight - window.innerHeight 的差值,可以间接判断DevTools是否开启。
// 利用窗口内外尺寸差判断
const threshold = 150; // 设置一个阈值
setInterval(() => {
if (window.outerWidth - window.innerWidth > threshold || window.outerHeight - window.innerHeight > threshold) {
console.log('开发者工具可能已打开!');
// 执行反调试逻辑
}
}, 1000);
4. 🕵️♂️ 利用 console.log 的特性
console.log 在打印对象时,会触发对象内部的 getter。开发者可以重写某个对象的 toString 或 valueOf 方法,或者定义一个带有 getter 的属性。当你在控制台打印这个对象时,预设的 getter 就会被调用,从而暴露你的调试行为。
// 当你在控制台打印这个对象时,就会触发反调试逻辑
let devtools = {
open: false,
toString: function() {
this.open = true;
// 在这里执行反调试代码
console.error('检测到调试行为!');
return 'DevTools Detected';
}
};
console.log('%c', devtools); // 打印这个特殊对象来触发检测
5. ⏱️ 代码运行时间差
某些操作在打开开发者工具时会变慢。例如,执行一段复杂的计算。通过比较正常执行和疑似调试状态下的时间差,可以判断是否存在调试行为。
🛠️ 怎么做:见招拆招的绕过技巧
面对这些“陷阱”,我们当然不能坐以待毙。以下是一些常用的“反反调试”策略:
1. 🚫 一键禁用所有断点 (Deactivate Breakpoints)
这是应对无限 debugger 最直接的方法。在Chrome开发者工具的“源代码(Sources)”面板中,按下 Ctrl + F8 (或点击对应的图标),可以临时禁用所有断点,让脚本顺畅执行下去。
2. 🎯 局部禁用与条件断点
如果不想完全禁用断点,可以右键点击 debugger 所在的那一行,选择“永不在此处暂停 (Never pause here)”。或者,更高级的玩法是设置一个条件断点,让断点在一个永远不会成立的条件下触发(例如,false),从而巧妙地跳过它。
3. 🔄 替换文件大法 (Override)
这是非常强大的一招。
-
在“源代码(Sources)”面板找到目标JS文件。
-
进入“替换(Overrides)”标签页,启用本地替换。
-
将目标JS文件保存到本地,然后用你喜欢的编辑器修改它,比如直接注释掉所有
debugger语句或反调试函数。 -
刷新页面,浏览器就会加载你修改后的本地版本,所有“机关”都被你提前拆除了!
4. 🔧 抓包工具修改响应 (Burp Suite / Fiddler)
与本地替换类似,你可以使用Burp Suite等抓包工具,设置一个响应修改规则。当浏览器请求目标JS文件时,抓包工具会自动将响应内容中的反调试代码(如 debugger 关键字)替换为空字符串,从源头上解决问题。
5. 🐒 油猴脚本 + Hook
对于更复杂的反调试逻辑,比如检测函数 toString,我们可以使用油猴 (Tampermonkey) 脚本,在页面脚本执行前注入我们自己的代码。通过 Hook 技术,我们可以重写或“劫持”那些被用于检测的原始函数(如 Function.prototype.toString),让它们返回一个“无害”的结果,从而骗过反调试脚本。
// 一个简单的油猴脚本示例,用于Hook toString方法
(function() {
'use strict';
const originalToString = Function.prototype.toString;
Function.prototype.toString = function() {
if (this.name.includes('your_target_function_name')) {
return 'function() { [native code] }'; // 返回伪造的本地代码字符串
}
return originalToString.call(this);
};
})();
✨ 总结时刻
好了,今天的JS逆向攻防战就先到这里。我们来快速回顾一下核心要点:
-
是什么:JS反调试是阻止代码被动态分析的技术。
-
为什么:通过无限
debugger、监听键盘、检测窗口尺寸等多种方式实现检测。 -
怎么做:我们可以通过禁用断点、文件替换、抓包修改、Hook函数等多种“反反调试”技巧进行绕过。
掌握这些技术,就像拥有了探索JS世界的“万能钥匙”。当然,攻与防的博弈永远不会停止,新的技术总在不断涌现。
最后,留给大家一个思考题:
如果一个网站的反调试逻辑是写在 WebAssembly (WASM) 里的,你觉得应该从哪些角度去分析和绕过呢?
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:AlphaNet Сяо Яо Сяо Яо《第90天-JS逆向终极对决:当“反调试”遇上“反反调试”》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论