断点调试入门
本节目标
- 理解 DevTools 里「断点」怎么帮你卡住加密执行的那一刻
- 掌握 Sources 面板下 XHR/fetch 断点与条件断点
- 会看「调用栈(Call Stack)」顺藤摸瓜
当你在 JS 里搜到一个疑似加密函数,下一步就是让程序在这里暂停,看输入是什么、输出是什么。
DevTools → Sources → 在文件里点行号下断点
或在代码里写 debugger; 语句,运行到这自动停XHR/fetch 断点是逆向利器:让「任何发往某 URL 的请求」在发送前暂停,你直接停在「加密参数刚算完、准备发请求」的那一行。
// 运行环境:Node.js 18+(无需依赖)
// 运行:node jsr-l3.cjs
// 用代码演示「调用栈」概念:被加密函数调用的链条
function encrypt(value) { // ③ 最终算密文的地方
return 'ENC:' + Buffer.from(value).toString('base64')
}
function buildRequest(user) { // ② 组装请求
const token = encrypt(user.name) // 调用 encrypt
return { url: '/api', token }
}
function onClick() { // ① 入口(事件触发)
const user = { name: 'Laowen' }
return buildRequest(user) // 调用 buildRequest
}
// 在 DevTools 里,从 onClick 一路点进 encrypt,Call Stack 会显示
// onClick → buildRequest → encrypt 这条链
console.log(onClick())关键操作:下断点后触发请求,DevTools 会在 Sources 面板高亮当前行,右侧 Call Stack(调用栈) 从上到下就是「谁调用了谁」。点上去就能跳到对应代码——这正是你从「加密结果」反推「加密函数」的路径。
名词解释
断点(Breakpoint):让程序「运行到某一行时暂停」的标记。它像在代码里设了个路障,车开到这就停,让你能检查此刻所有变量的值。逆向里断点是「进入加密现场」的唯一门票。
调用栈(Call Stack):记录「当前这行代码,是被谁一层层调用进来的」的列表。栈顶是正在执行的函数,往下是它的调用者。逆向时你常从一个「算完的结果」倒着点 Call Stack,就能找到「最初是谁发起这次计算的」。
课后练习
练习 1:XHR/fetch 断点和普通行号断点,在逆向「加密参数」时哪个更省事?
答案:XHR/fetch 断点更省事。它直接在「请求即将发出」那一刻暂停,你看到的是「所有参数都已算好」的最终状态,不用猜加密发生在哪一行。普通行号断点得你先猜对函数位置才能下。
练习 2:为什么 debugger; 语句在「生产环境压缩代码」里可能被移除或不生效?
答案:生产构建常开启「摇树/压缩」会删掉
debugger;语句;且有些网站用eval动态执行、或做了反调试(检测 devtools 打开就卡死)。所以debugger;适合本地调试,线上逆向更多靠 XHR 断点和搜索关键字。
总结
断点调试是我认为「逆向里最该先练熟」的硬功夫。我的观点很直接:不会用断点,等于蒙着眼睛找人。很多人习惯「搜索关键字 → 通读整个函数」,但当函数被压缩成 function(a,b){...} 且嵌套十层时,通读既慢又容易迷路。正确姿势是:先下 XHR 断点「卡在请求发出前」,再顺着 Call Stack 一层层往上点,每一层只看「这一步干了啥」,很快就能定位到真正的加密函数。记住:断点让你「看现场」,搜索让你「找位置」,两者配合才是完整打法。