64:JS反调试与代码混淆(原理+绕过+还原)
本讲是JS逆向系列的进阶内容,核心聚焦 “JS反调试机制的识别与绕过” 和 “代码混淆的识别与还原”——这两类都是前端安全防护的常见手段,目的是阻止他人调试、窃取敏感JS逻辑(如加密算法)。笔记以“反调试(定义→检测→绕过)”和“混淆加密(定义→类型→还原)”为两大主线,结合实操案例拆解,突出“可落地的绕过/还原策略”。
一、JS反调试:识别与绕过
1. 什么是JS反调试?
网站通过特定JS代码限制/禁止开发者工具调试,核心目的是保护前端敏感逻辑(如加密算法、接口地址),常见手段分两类:
- 主动干扰调试:通过 debugger 语句制造死循环,让调试器反复暂停,无法正常分析;
- 禁用调试工具:拦截F12、右键菜单等操作,直接禁止打开开发者工具。
2. 如何检测反调试?
检测方法简单直接,核心是“尝试调试”,具体场景:
-
按F12无反应、右键菜单被禁用(提示“禁止调试”);
-
打开开发者工具后,页面立即暂停(反复出现debugger)、崩溃或无网络数据包;
-
其他隐蔽检测手段(前端代码层面):
- 监听键盘事件(拦截F12按键);
- 检测浏览器窗口高度差(开发者工具打开会改变窗口尺寸);
- 检测window.debugger等调试相关变量;
- 利用console.log调用次数、代码执行时间差判断是否被调试。
3. 核心绕过方法(原理+实操+优缺点)
针对“debugger死循环”类反调试,以下是5种高频绕过策略,按“实用性优先级”排序:
(1)本地覆盖法(推荐,通用性最强)
-
原理:将远程包含反调试代码的JS文件下载到本地,删除/注释debugger或反调试函数,再让浏览器加载本地修改后的文件(覆盖远程文件)。
-
实操步骤(以Chrome为例):
- F12打开“源代码”面板,找到触发反调试的JS文件(可全局搜索debugger);
- 右键文件 → 选择“替换内容”/“保存内容以备替换”,将文件保存到本地文件夹;
- 在本地文件中删除debugger语句或注释反调试函数(如enableDebugProtect());
- 在“源代码”面板的“替换”标签页中启用本地文件覆盖,刷新页面即可正常调试。
-
优点:彻底移除反调试代码,不影响自身断点调试;
-
缺点:配置稍复杂,若网站有多个反调试文件(如动态注入的JS),需逐一覆盖。
(2)条件断点法(高效,适合明确debugger位置)
-
原理:给debugger语句设置“永远不成立”的条件(如false),让调试器跳过该语句。
-
实操步骤:
- 打开开发者工具,当页面暂停在debugger处时,右键debugger所在行;
- 选择“添加条件断点”,输入false,点击确定;
- 刷新页面,debugger因条件不成立不再执行,可正常设置自己的断点。
-
优点:操作简单,不影响自身调试;
-
缺点:需明确debugger所在行,若有多个debugger需逐一设置。
(3)永不暂停法(快速临时绕过)
-
原理:利用Chrome开发者工具的“一律不在此处暂停”功能,手动标记debugger行,让调试器直接跳过。
-
实操步骤:
- 页面暂停在debugger处时,右键debugger所在行;
- 选择“一律不在此处暂停”,该行会被标记为“跳过”;
- 刷新页面,调试器不再在该位置暂停。
-
优点:操作极简单,适合临时绕过少量debugger;
-
缺点:对动态注入的debugger(如eval("debugger"))失效(行号会变化),多debugger场景需逐一标记。
(4)禁用断点法(应急方案)
-
原理:直接禁用开发者工具的所有断点功能,让debugger语句无法触发暂停。
-
实操步骤:
- 打开开发者工具的“源代码”面板;
- 点击顶部的“禁用断点”按钮(图标为“暂停+斜杠”);
- 刷新页面,debugger不再触发暂停,可正常抓包、查看源码。
-
优点:操作简单,快速绕过所有debugger;
-
缺点:“伤敌一千自损八百”——禁用后自己也无法设置断点调试。
(5)函数置空法(进阶,适合全局反调试函数)
-
原理:若反调试是通过全局函数(如setInterval循环调用debugger、console.clear()清空控制台)实现,可在控制台将这些函数置空,使其失效。
-
实操步骤:
- 找到触发反调试的全局函数(如function enableDebug() { debugger; });
- 在控制台执行enableDebug = function() {}(将函数置空);
- 刷新页面,反调试函数被改写,不再生效。
-
优点:精准绕过,不影响其他功能;
-
缺点:需先定位反调试函数;若网站检测原生函数是否被改写(如校验Function.toString长度),则失效。
4. 特殊场景:禁用F12的绕过
针对“直接禁止打开F12”的反调试,无需复杂操作,两种简单绕过:
- 方法1:先打开新标签页,开启开发者工具后,再在该标签页访问目标网站;
- 方法2:打开目标网站后,连续按两次F12(第一次触发禁用提示,第二次强制打开);
- 方法3:通过浏览器菜单打开开发者工具(如Chrome:更多工具→开发者工具)。
二、JS混淆加密:识别与还原
1. 什么是JS混淆加密?
通过特定算法将可读的JS代码转换为“面目全非但仍可执行”的代码,核心目的是保护敏感逻辑(如加密算法、接口密钥),避免被轻易窃取。
根据加密强度和成本,分为三类:
- 开源免费:小公司常用,如JJEncode、AAEncode、JSFuck;
- 商业收费:中型公司常用,如jsjiami、sojson;
- 自研加密:大公司专用,安全性最高,还原难度极大。
2. 开源混淆加密(识别+还原)
(1)核心特点
- 加密后代码特征明显(全是特殊字符、表情、数字等);
- 还原成本低,网上有大量免费在线解密工具。
(2)案例演示(以JJEncode、AAEncode、JSFuck为例)
① 原始代码
function printLing() {
console.log('ling');
}
printLing(); // 输出:ling
② 加密效果
-
JJEncode:加密后全是符号和字母组合,如:
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$_;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+"console.log('ling')"+"\"")())(); -
AAEncode:加密后全是表情符号,如:
ヽ(´▽`)ノfunctionヽ(´▽`)ノprintLingヽ(´▽`)ノ(){ヽ(´▽`)ノconsole.logヽ(´▽`)ノ(´ling´)ヽ(´▽`)ノ}printLingヽ(´▽`)ノ()ヽ(´▽`)ノ -
JSFuck:加密后仅用[]()!+五种字符,如:
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]])([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]])([]+(![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([][[]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+!+[]]+([]+![])[!+[]+!+[]+!+[]]+(![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]])()
③ 还原方法
-
方法1:在线解密工具(推荐):
- 常用工具:JS解密网(https://www.jsjiami.com/jiemi.html)、站长工具JS解密;
- 操作:复制加密代码→粘贴到工具→点击解密→获取原始代码。
-
方法2:手动简化(应急):
- 开源混淆代码的核心是“最后通过括号执行”,可删除加密代码末尾的执行括号(如()),在控制台运行,强制报错泄露原始代码;
- 示例:删除JJEncode加密代码末尾的();,运行后会报错,错误信息中可能包含原始函数名/逻辑。
3. 商业混淆加密(识别+还原)
(1)核心特点
- 加密后代码保留基本JS格式,但变量名、函数名被随机混淆(如a123、x7f9),包含大量冗余代码、控制流平坦化;
- 常见标识:代码开头/结尾可能有// jsjiami.com、// sojson.com等水印。
(2)案例演示(以jsjiami为例)
① 识别加密方式
访问目标网站(如https://www.eisk.cn/Tides),F12查看JS文件,发现代码变量名随机、有// jsjiami.com水印,确定为jsjiami商业混淆。
② 还原方法
-
方法1:免费在线解密工具(优先尝试):
- 常用工具:JSDec(https://www.liulihaocai.com/jsdec.html)、查错网AES解密(https://www.chacuo.net/jsencryptaes);
- 操作:复制混淆代码→粘贴到工具→点击解密→获取可读性更高的代码(可能无法完全还原,但可提取核心逻辑)。
-
方法2:付费破解:
- 若免费工具失效,可在第三方平台(如猪八戒)找专业人员破解,费用根据加密强度而定;
-
方法3:动态调试还原(进阶):
- 若无法直接解密,可通过断点调试,追踪混淆代码的执行流程,提取核心逻辑(如加密函数、密钥);
- 关键:找到入口函数(如点击按钮触发的函数),逐步调试,忽略冗余代码。
③ 注意事项
- 部分商业混淆会加入“反还原”机制(如调试时崩溃、代码自毁),需先通过前面的反调试绕过方法处理;
- 还原后若涉及AES/DES等加密,需从代码中提取密钥(key)、向量(IV),再用对应工具解密数据。
三、核心总结
-
反调试绕过优先级:本地覆盖法(最优,彻底移除反调试)→ 条件断点法(精准)→ 永不暂停法(临时)→ 禁用断点法(应急)→ 函数置空法(进阶);
-
混淆还原核心思路:
- 开源混淆:直接用在线工具解密,应急可手动删执行括号报错泄露;
- 商业混淆:先找免费工具,失效则付费破解或动态调试提取核心逻辑;
- 自研混淆:还原难度极大,若无法突破可考虑放弃;
-
实战关键:
- 反调试与混淆常同时存在,需先绕过反调试,再进行混淆还原;
- 调试时多利用“全局搜索”(如debugger、encrypt、混淆水印)快速定位核心代码;
- 优先使用浏览器原生功能(本地覆盖、条件断点),避免依赖第三方工具,提高兼容性。
学习本讲的核心是“灵活应对”——不同网站的反调试/混淆策略不同,需结合实际场景选择合适的方法,多复现案例才能熟练掌握。如果遇到复杂的自研混淆或多层反调试,可优先聚焦“核心功能触发的函数”,忽略无关的防护代码,提高效率。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)