JS逆向-断点调试与反绕过技巧

📅 2026/7/8 14:52:30 👁️ 阅读次数 📝 编程学习
JS逆向-断点调试与反绕过技巧

📝 渗透测试角度优化笔记:JS逆向基础、反调试与实战应用

1. JS逆向与Web安全的关联

JS逆向是前端分析的核心技术,它并非孤立的代码审计,而是与Web安全测试紧密相连。其主要应用场景包括:

  • 突破前端防护:分析登录加密、Sign签名、参数混淆等机制,为后续的暴力破解、数据篡改、接口越权等攻击铺路。
  • 发现隐藏攻击面:从JS文件中提取API接口、敏感参数、甚至硬编码的密钥或调试信息。
  • 逻辑漏洞挖掘:分析前端折扣计算、验证码生成、支付逻辑等,寻找可被利用的业务缺陷。

2. 开发者工具(F12)核心面板使用指南

面板名称

核心功能

在逆向与安全测试中的应用

👁️元素 (Elements)

查看和实时编辑页面的HTML结构与CSS样式。

用于定位与数据提交相关的DOM元素(如表单字段、隐藏值),或观察页面元素的变化(如验证码图片刷新)。

🖥️控制台 (Console)

执行任意JavaScript代码,查看日志和错误信息。

1. 测试变量/函数:在断点处,可直接在控制台输入变量名查看其值,或调用已加载的函数。
2. 定位加密入口:搜索可能的关键词,如encryptsignmd5

🌐网络 (Network)

监控所有网络请求的详情(Header、参数、响应)。

核心入口
1.抓包分析:找到目标请求(如登录、提交订单),分析其请求参数(尤其是加密参数如signtoken)。
2.启动器 (Initiator):查看请求由哪个JS文件的哪一行发起的,快速定位加密代码的位置。

📜源代码/来源 (Sources)

核心调试面板。可查看所有加载的资源(JS、CSS)、设置断点、单步执行、查看调用栈和作用域。

逆向主战场
1.文件查找:通过搜索(Ctrl+Shift+F)全局搜索关键词,定位加密函数所在文件。
2.断点调试(详见下文)。
3.调用栈分析:理清代码执行顺序,找到加密函数的调用源头。

📦应用程序 (Application)

查看和管理本地存储(Cookie、LocalStorage、SessionStorage)、缓存等。

用于检查前端存储的敏感信息(如令牌、用户信息),或分析存储对应用状态的影响。


3. 核心逆向技术:断点调试六种姿势

断点是暂停代码执行、观察运行时状态的最有效手段。以下是六种常用断点及其在逆向中的应用场景:

断点类型

如何设置

主要应用场景

🔵正常断点

在Sources面板的代码行号上单击。

基础调试。分析核心加密函数、参数生成逻辑的每一步执行过程。

🟡条件断点

右键行号 → “添加条件断点”,输入条件表达式。

精准定位。只在满足特定条件(如data.id === 10086i === 5)时暂停,适用于循环或处理大量数据时。

🌸日志断点

右键行号 → “添加日志断点”,输入要输出的表达式。

插桩分析。无需暂停代码,仅在命中断点时输出日志。非常适合分析复杂的虚拟机和混淆代码,可以打印出关键寄存器和变量的值。

📡XHR断点

Sources → XHR/提取断点 → “+”添加URL包含的关键字。

定位请求。当希望拦截所有包含特定关键字(如/api/login)的Ajax请求时,代码会自动断在send()方法处,轻松找到请求的发送源头。

🖱️事件断点

Sources → 事件监听器断点 → 展开并勾选目标事件(如click)。

分析交互。用于调试由用户操作触发的功能,特别是滑块验证码、图片点击等场景,可以捕捉到事件处理函数。

🌳DOM断点

元素面板 → 右键目标元素 → 中断 → 子树修改/属性修改/节点移除。

追踪DOM变化。当页面元素被动态修改、添加或删除时(如翻页加载、弹窗出现),可以断下并追溯修改DOM的JS代码。


4. 调用堆栈分析:理清代码执行逻辑

当断点触发时,调用堆栈 (Call Stack)面板会显示当前函数的调用链。在逆向中,它的作用是:

  • 追溯源头:从当前断点位置(如加密函数内部)向上查看,找到是谁调用了这个函数,最终找到参数传入的起点。
  • 理解流程:分析整个加密逻辑的执行顺序,避免在嵌套的异步回调或复杂的函数调用中迷失方向。

5. 反调试技术概览

反调试的目的是阻止或干扰开发者工具的调试功能,使逆向分析者难以动态跟踪代码执行。根据其实现方式,主要分为以下几类:

类别

代表技术

检测原理

绕过思路

无限循环/断点

无限Debugger

利用debugger;语句或setInterval触发断点,使调试器不断暂停。

禁用所有断点、替换文件、条件断点。

键盘事件监听

监听F12、Ctrl+Shift+I等

监听keydown事件,阻止开发者工具打开。

修改事件监听、Burp替换响应、油猴脚本。

环境特征检测

检测窗口大小差异、console对象、devtools变量等

通过比较窗口内外尺寸、console.log调用次数、Function.prototype.toString检测等判断调试器是否打开。

Hook相关函数、修改返回结果、使用无头浏览器。

时间差异检测

测量代码执行时间

调试状态下代码执行速度变慢,通过时间差判断。

设置条件断点跳过检测、修改时间计算逻辑。

非浏览器检测

检测User-Agent、navigator属性等

识别自动化工具或非标准浏览器环境。

伪造User-Agent、模拟浏览器环境。


6. 常见反调试技术详解与绕过实战
6.1 无限Debugger
  • 原理:在关键代码前插入debugger;语句,或通过setInterval不断触发,导致调试器无限暂停。
    ``javascript
    (function() {
    function evil() {
    debugger;
    setTimeout(evil, 100);
    }
    evil();
    })();
    ``
  • 绕过方法
    *禁用所有断点:在Sources面板点击“Deactivate breakpoints”按钮(或按Ctrl+F8),临时忽略所有debugger断点。
    *设置条件断点:在debugger行上右键选择“条件断点”,输入false,使其永远不触发。
    *替换文件:使用Burp Suite或油猴插件,将响应中的debugger替换为空白。
6.2 键盘事件监听阻止打开调试工具
  • 原理:监听keydown事件,当按F12或Ctrl+Shift+I等组合键时,阻止默认行为或弹窗警告。
    ``javascript
    document.addEventListener('keydown', function(e) {
    if (e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I')) {
    e.preventDefault();
    return false;
    }
    });
    ``
  • 绕过方法
    *使用菜单打开:在浏览器菜单中手动选择“开发者工具”。
    *Burp替换:拦截响应,移除事件监听代码。
    *油猴脚本:注入脚本解除事件监听,如window.removeEventListener('keydown', listener, true)
6.3 检测开发者工具状态
  • 原理:利用console.log调用次数、console.profileFunction.prototype.toString等方法判断调试器是否打开。
    ``javascript
    var c = 0;
    setInterval(function() {
    console.log(c++);
    if (c > 100) alert('调试中!');
    }, 100);
    ``
  • 绕过方法
    *Hookconsole.log:在控制台执行console.log = function(){},使其失效。
    *修改检测逻辑:通过Burp或油猴替换相关代码,或使用Object.defineProperty重写属性。
6.4 时间差检测
  • 原理:在调试模式下,代码执行速度会显著变慢。通过测量两段代码之间的时间差,判断是否处于调试状态。
    ``javascript
    var start = Date.now();
    for (var i = 0; i < 10000000; i++) { /* 空循环 */ }
    var end = Date.now();
    if (end - start > 100) alert('调试中!');
    ``
  • 绕过方法
    *跳过检测:在Date.now()处设置条件断点,修改返回值。
    *使用脚本自动化:用无头浏览器(如Puppeteer)运行,避免手动调试。
6.5 非浏览器环境检测
  • 原理:检测navigator.webdrivernavigator.pluginswindow.chrome等属性,识别自动化工具。
  • 绕过方法
    *使用puppeteer-extra并安装stealth插件,模拟真实浏览器。
    *手动修改属性:在控制台执行Object.defineProperty(navigator, 'webdriver', {get: () => undefined})

7. 实战应用思路:从逆向到漏洞利用

将以上技巧串联起来,形成从发现到利用的闭环:

  1. 捕获目标:在网络面板找到包含可疑参数(如signtoken)的请求。
  2. 定位代码:右键请求 → “启动器” 查看调用栈,或在Sources面板中全局搜索加密参数名。
  3. 设置断点
    * 如果找到了疑似加密函数,在函数入口处设置正常断点。
    * 如果想拦截所有API请求,设置XHR断点。
    * 如果是验证码点击,设置事件断点。
  4. 触发与调试:重新触发操作(如点击登录),代码在断点处暂停。此时:
    * 查看作用域,观察变量值,找到生成sign的原始数据和算法。
    * 利用调用堆栈,向上追溯,理解数据流。
    * 在控制台中测试函数,或修改变量值观察影响。
  5. 模拟与验证
    * 分析清楚后,可以使用Python、Node.js等语言模拟出加密算法。
    * 在Burp Suite中构造请求,使用模拟的算法生成合法参数,尝试绕过前端限制进行漏洞测试(如越权、爆破、篡改价格)。

关键技巧

  • 先禁用所有断点:快速跳过无限debugger
  • 使用XHR断点定位请求:如果加密由请求触发,直接对请求URL设XHR断点,定位发送位置,绕过前端检测。
  • 利用条件断点精准暂停:在可疑函数入口设条件断点,避免频繁暂停。
  • 结合Burp替换响应:将服务器返回的JS文件中的反调试代码删除,然后重放请求。

8. 常用工具与插件
  • 油猴插件(Tampermonkey):编写脚本动态修改页面代码,移除反调试。
  • Burp Suite:拦截响应,使用“Match and Replace”功能删除反调试代码。
  • Chrome DevTools 内置功能
    *禁用断点Ctrl+F8
    *黑盒脚本:在Sources面板右键JS文件,选择“Blackbox Script”,忽略该文件的断点。
    *条件断点:在行号上右键设置。
  • Puppeteer/Playwright:自动化浏览器,配合--auto-open-devtools-for-tabs参数调试。

9. 总结

JS逆向是连接前端分析与后端漏洞挖掘的桥梁。掌握开发者工具的使用,特别是六种断点的灵活运用调用堆栈的分析,是解开前端黑盒的关键。从网络请求入手,顺藤摸瓜找到加密逻辑,再通过断点调试还原算法,最终将成果应用到渗透测试中。

同时,反调试技术是JS逆向中的一道门槛,但并非不可逾越。掌握常见的反调试原理及其绕过方法,可以帮助你在渗透测试中顺利突破前端限制,深入分析加密逻辑。

核心目标:获取签名算法、提取加密参数,从而更有效地进行漏洞挖掘(如越权、注入、爆破等)。希望本笔记能成为你工具箱中实用的一页。