概述
浏览器的调试工具在 JavaScript 逆向工程中,帮助开发者分析和理解代码执行流程、变量值及其变化,从而揭示隐藏逻辑和加密机制,为破解、修改或复现代码提供重要支持。
调试面板详解
谷歌浏览器的调试面板概览:
顶部操作栏
脚本执行
快捷键
F8
按钮的两种状态
暂停脚本执行
提示:Pause script execution
说明:暂停脚本执行;浏览器会立即暂停所有 JavaScript 代码的运行,不论代码当前执行到哪里。这对于实时排查问题非常有帮助。
图标:
恢复脚本执行
提示:Resume script execution
说明:恢复脚本执行;脚本会继续从上次暂停的位置开始执行,直到遇到下一个断点或者执行完毕。
图标:
单步跳过
快捷键:F10
提示:step over
说明:按钮来让代码进入下一个函数调用。
- 执行下一行代码,但不会进入函数内部,它在意的是执行调用结果。
- 当遇到自定义函数的时候,会在后台静默调用,直接得出结果。
图标:
单步进入
快捷键:F11
提示:step into
说明:进入到当前行函数调用的内部。适合需要查看函数内部具体执行逻辑的情况。
图标:
单步跳出
快捷键:Shift + F11
提示:step out
说明:继续执行当前函数,直到返回调用该函数的位置。适合已经深入函数内部,想要返回到外部调用代码的位置。
图标:
跳出深层函数调用:你已经深入到多个嵌套函数内部,并希望返回到更高层次的调用位置。
快速查看调用结果:对某个函数的内部实现已经足够清楚,想快速跳出该函数并继续查看调用者的执行。
调试性能问题:跳出冗长的函数逻辑,迅速回到调用代码,以关注整体流程或数据流。
单步执行
提示:F9
说明:一步步执行代码,不会区分任何自定义函数,所有脚本代码都会依次执行。
图标:
数据面板
Threads
Threads 部分用于显示和管理 JavaScript 的执行线程。现代浏览器通过多线程技术来提高性能和响应速度,尤其是在处理复杂或长时间运行的任务时。理解和使用 Threads 部分对于调试和优化多线程应用程序非常重要。
- Main Thread:主要线程,负责处理页面的 UI 渲染、用户交互和大部分 JavaScript 代码的执行。
- Web Workers:独立于主线程之外的后台线程,用来执行耗时的操作(如数据处理),从而不阻塞主线程的渲染和用户交互。
Watch
它允许你在代码执行过程中监视特定的变量或表达式。这对于调试复杂的逻辑和动态监控变量的值非常有用。
注意:这个是针对浏览器级别设置的,就是你针对A网页添加的watch,在其他的B网页也是生效的。
BreakPoints
断点设置可选项:
- Pause on uncaught exceptions:用于在未捕获的异常发生时暂停JavaScript执行。
- Pause on caught exceptions:如果JavaScript代码捕获了一个异常,执行将会自动暂停,你可以查看调用栈和变量状态,从而进行调试。
Scope
显示了当前代码执行上下文中的所有变量,包括局部变量、全局变量、闭包变量等。
- Local:当前执行上下文中的局部变量。
- Closure:闭包变量,如果当前函数是一个闭包。
- Global:全局变量。
鼠标右键点击变量还可以进行以下操作:
Call Stack
当前代码执行位置的调用堆栈(形象理解:类似步枪弹夹的先进后出的数据结构),列出了所有活动函数的调用顺序。每次代码在断点处暂停时,Call Stack 会显示每个函数调用的层次结构,从最底层的调用(函数入口)到当前暂停的位置。
执行顺序是从下到上查看的。
- 了解函数的调用链和顺序。
- 查看并导航到每个函数调用的具体位置。
- 返回到之前的函数调用位置,检查它们的变量和状态。
function functionA() {
functionB();
}
function functionB() {
functionC();
}
function functionC() {
debugger; // 这里设置一个断点
}
functionA();
调用堆栈顺序:
补充:anonymous(匿名的) 出现在调用栈中的原因是 JavaScript 代码执行时,某些函数或代码块没有明确的名称。通过给函数命名,尤其是在事件处理程序、立即执行函数和其他匿名函数中,可以使调用栈更具可读性,从而更容易调试和理解代码执行的路径。
XHR / fetch BreakPoints
如果要在 XHR 的请求网址包含指定的 字符串。DevTools 会在 XHR 调用 send() 的代码行暂停。
可以针对想要的XHR接口进行断点拦截。
- 检查调用堆栈:查看调用堆栈,了解请求是从哪里发起的。
- 检查请求数据:通过 Network 面板和 XHR/Fetch details,检查请求的头信息、主体和响应数据。
- 继续执行:你可以选择继续执行代码,单步执行,或跳过当前断点。
DOM BreakPoints
在DOM元素发生特定变化时暂停JavaScript执行。
DOM 更改断点的类型
子树修改。当当前所选节点的子级被移除或 或更改子元素的内容。未在子节点属性更改时触发,或 对当前所选节点进行任何更改。
属性修改:在 当前选定的节点时,或当属性值发生更改时。
节点移除:在移除当前选定的节点时触发。
右键点击DOM断点弹出以下内容:
Global Listener
指的是那些直接附加到全局对象(如 window 和 document)上的事件监听器。这些监听器可能负责处理页面加载、用户交互、窗口大小变化等全局性事件。
window.addEventListener('resize', function() {
console.log('Window resized');
});
document.addEventListener('click', function() {
console.log('Document clicked');
});
在 DevTools 的 Event Listeners 面板中,你可以找到这些监听器:
- 在 window 的 resize 事件下,会显示附加的监听器及其相关信息。
- 在 document 的 click 事件下,会显示附加的监听器及其相关信息。
查看全局监听器有助于:
- 调试全局事件处理:了解哪些事件被监听可以帮助你调试和优化你的应用。
- 性能分析:附加过多的全局监听器可能影响性能,通过检查这些监听器,可以识别和优化不必要的监听器。
- 排除错误:有时候由于监听器被错误地附加在全局对象上,会导致一些意想不到的问题,通过查看全局监听器,可以快速定位并修复这些问题。
Event Listener BreakPoints
如果要暂停在某事件监听器代码之后运行的事件监听器代码,可以使用事件监听器断点 事件。您可以选择特定事件(例如 click)或事件类别。
选中其中一个类别即可在触发该类别的任何事件时暂停,或展开 选择类别并选中特定事件。
事件归类 | 归类说明 | 事件说明 |
---|---|---|
Ad Auction Worklet | 这个面板主要用于帮助开发者理解和诊断在浏览器内执行广告拍卖的过程。 |
|
Animation | 设置 Animation 事件监听断点是调试动画代码。通过这种方式,你可以在动画相关事件(例如 animationstart、animationend、animationiteration)触发时暂停代码执行,并深入查看动画的执行情况。这对于优化动画性能和调试动画逻辑特别有帮助。 |
|
Canvas | 设置 Canvas 事件监听断点,是调试和优化使用 Canvas 进行绘图和动画的有效工具。 |
|
Clipboard | 调试与剪贴板相关操作,可以帮助开发者了解和优化用户与应用程序之间的剪贴板交互。 |
|
Control | 调试与表单控件、窗口大小和滚动操作等相关事件,可以帮助开发者深入了解和优化用户界面的交互体验。 |
|
Device | 调试与设备传感器和方向变化相关事件 |
|
DOM Mutation | 调试和分析与 DOM 变动相关的操作。 |
|
Drag / drop | 调试与拖放操作相关事件。 |
|
Geolocation | 调试与地理定位相关事件 |
|
Keyboard | 调试与键盘输入相关事件 |
|
Load | 调试与页面加载相关事件 |
|
Media | 调试与媒体元素相关事件 |
|
Mouse | 调试与鼠标交互相关事件 |
|
Notification | 调试与通知相关事件,关键通知事件如 click 和 close 上设置断点,你可以详细分析和优化通知互动的过程,确保用户体验的流畅和可靠。 |
|
Parse | Parse 事件监测是一种用于监测代码解析阶段的事件,它属于较低层级的调试技术 |
|
Picture-in-Picture | 调试与视频画中画模式相关事件 |
|
Pointer | 调试鼠标、触控笔和触摸屏等多种输入事件 |
|
Script | 设置 Script 类别的事件监听断点 |
|
Shared Storage Worklet | 调试共享存储相关操作 |
|
Timer | 可以有效调试与定时器相关的 JavaScript 代码。无论是 setTimeout、setInterval 还是清除相应的计时器,设置这些断点可以帮助你精确捕捉和分析代码执行过程中的计时器行为 |
|
Touch | 有效调试与触摸事件相关的 JavaScript 代码 |
|
WebAudio | 调试与 WebAudio 相关的 JavaScript 代码,捕获音频处理事件还是状态变化事件 |
|
Window | 调试与 Window 对象相关的 JavaScript 代码。这对于捕获和处理窗口事件非常有帮助,能够帮助你更好地理解和优化你的页面行为和用户交互逻辑。 |
|
Worker | 设置 Web Worker 的事件监听断点,可以有效调试与 Web Worker 相关的 JavaScript 代码。 |
|
XHR | 这对于捕获和处理 HTTP 请求和响应 |
|
谷歌浏览器事件监听断点的调试面板,XHR
CSP Violation Breakpoints
Trusted Type Violation
基于 DOM 的跨站脚本攻击是指,当用户控制 来源(例如用户名,或取自网址片段的重定向网址) 到达一个接收器,它是一个类似于 eval() 的函数或一个属性 setter(如 .innerHTML,可执行任意 JavaScript 代码。
- Sink Violations:用于监测潜在的安全性问题,如反射型跨站脚本(XSS)攻击或者数据置换问题。Sink Violations 断点帮助开发者在脚本修改 DOM 或执行高度敏感操作时及时捕捉这些行为。
- Policy Violations:捕获和处理跨域请求错误以及内容安全策略违规非常有帮助,能够帮助你更好地理解和遵守安全策略。
技巧
打代码行断点
手动打断点
点击行号数字前的空白区域,可以添加断点。同时右键点击断点可以将其设置为条件断点(满足条件才进入断点)。
代码中打断点
在代码中调用 debugger
即可暂停到该行。这相当于代码行 断点,只不过是在代码中设置断点,而不是在开发者工具界面中设置断点。
console.log('a');
console.log('b');
debugger;
console.log('c');
条件代码行断点
如果您想停止执行,但仅在满足某些条件时才可使用条件代码行断点。
当您想跳过与您的情况无关的断点时,尤其是在循环中时,此类断点会很有用。
如需设置条件代码行断点,请执行以下操作:
- 打开 Sources 面板。
- 打开包含您想要换行的代码行的文件。
- 转到代码行。
- 代码行的左侧是行号列。右键点击该图标。
- 选择添加条件断点。代码行下方会显示一个对话框。
- 在对话框中输入您的条件。
- 按 Enter 键激活断点。行号列顶部会显示一个带问号的橙色图标。
记录代码行断点
使用日志代码行断点(日志点)将消息记录到控制台,无需暂停执行,也无需使用 console.log() 调用让您的代码杂乱无章。
- 打开来源面板。
- 打开包含您想要换行的代码行的文件。
- 转到代码行。
- 代码行的左侧是行号列。右键点击该图标。
- 选择添加日志点。代码行下方会显示一个对话框。
- 在对话框中输入您的日志消息。您可以使用与调用 console.log(message) 相同的语法。
- 按 Enter 键激活断点。行号列顶部会显示一个包含两个点的粉色图标。
使用“永不暂停”跳过断点
使用此处一律不暂停代码行断点来跳过因其他原因发生的暂停。如果您已启用异常断点,但调试程序在您不想调试的特别嘈杂的异常上停止,这将非常有用。
如需将某个休息位置静音,请执行以下操作:
- 在 Sources(来源)面板中,打开源文件并找到您不希望换行的行。
- 右键点击左侧行号列中的行号,该行号位于导致换行的语句旁边。
- 从下拉菜单中选择一律不在此处暂停。该行旁边会出现一个橙色(条件)断点。
您还可以在执行暂停时将断点静音。请观看下一个视频,了解工作流程。
查看变量
- 将鼠标放置到变量身,可以查看当前变量在当前状态下的值。
- 划选来查看某一句表达式或语句的执行结果。