第 100 章 SourceMap 与前端源码恢复(Bundle Recovery)
现代前端(webpack/Vite/Next.js)把代码打包混淆成 bundle。恢复源码的黄金途径:SourceMap(如果泄露=直接还原源码)、bundle 结构分析(chunk 注册表/模块映射)。这是第 13 章 JS 逆向的深度延伸——前端逆向的第一步往往是"源码恢复"而不是"硬读混淆代码"。
📍 知识点地图 | 主题:SourceMap恢复 | 前置:第13章 | 后续:— | 核心概念:SourceMap、webpack结构、webcrack、chunk
100.1 前端构建产物结构(先懂形态)
现代前端构建(webpack/Vite/Next.js)产物:
bundle.js(打包后的主文件)
chunk(代码分割: 路由级/组件级)
manifest/chunk 注册表(模块→chunk 映射)
source map(.js.map,源码映射文件)
构建流程: 源码 → 打包(合并/压缩/混淆)→ 产物
逆向目标: 从产物回到"接近源码"的形态
100.2 SourceMap(源码恢复的黄金途径)
什么是 SourceMap
.js.map 文件: 记录了"压缩代码 → 原始源码"的完整映射
(每个 token 的位置映射 + 原始源码内容!)
如果网站把 .map 文件一起发布了 → 直接拿回源码
查找:
URL: bundle.js.map / static/js/main.js.map
bundle 尾注释: //# sourceMappingURL=xxx.map
目录枚举(第 57 章)
验证: DevTools → Sources → 看到 .map 对应源码
SourceMap 恢复源码
# 1. 下载 bundle + .map
curl -O https://target.com/static/js/main.js
curl -O https://target.com/static/js/main.js.map
# 2. 用工具还原(sourcemap 还原器/DevTools)
# DevTools: 直接打开 bundle(自动加载 .map → 源码视图)
# 或 node 脚本: source-map 库解析 .map → 输出源码文件树
# 3. 还原后 = 完整源码阅读(第 13 章方法直接可用)
SourceMap 泄露的危害
□ 完整源码(业务逻辑/算法/密钥常量)
□ 内部路径/模块结构(攻击面地图)
□ 注释(开发信息/遗留代码)
□ 未压缩的开发版本逻辑(比混淆版好读百倍)
100.3 无 SourceMap 的 bundle 恢复(硬核路线)
1. Bundle 结构分析(找模块边界)
webpack 格式特征:
chunk 注册表: 模块 ID → 函数(大数组)
模块函数: (module, exports, require) => { ... }
入口: 数组第一个元素(runtime)
分析:
1. 识别 webpack 包装(开头大数组+函数体)
2. 定位模块边界(按模块函数分割)
3. 提取每个模块的代码段
4. 按模块重组 → 逐模块分析
2. 工具链
webcrack: 自动去混淆+模块拆解(现代神器)
npx webcrack bundle.js -o output/ # 还原模块结构+美化
sourcify / jsnice: 变量命名美化
Babel/AST: 手动去混淆(第 13 章)
SourceMap 扫描器: 批量找 .map(目录/URL 扫描)
3. 手动提取(工具失效时)
□ 找 chunk 注册表(大数组)→ 模块边界
□ 找关键字符串(API 路径/错误信息)→ 所在模块
□ 单独分析目标模块(不需要全还原)
□ 记录: 模块 ID → 功能映射
100.4 框架专项(Next.js/Vue/React)
Next.js:
_next/static/chunks/ 结构(页面 chunk 命名规律)
buildManifest/ssgManifest(页面→chunk 映射)
RSC payload(服务端组件数据在 HTML/脚本里)
→ 页面路由 → 对应 chunk → 目标逻辑
Vue:
webpack chunk 按路由分割
app.js + chunk-vendors.js(第三方库)
runtime 结构类似 webpack
React SPA:
路由 chunk(按页面加载)
API 调用集中在服务层模块(第 13 章找接口)
100.5 完整恢复流程(端到端)
1. 发现 bundle(页面源码/Network 面板)
2. SourceMap 检查(尾注释/URL 探测)→ 有则直接还原
3. 无 map → 结构分析(webpack 识别 → 模块边界)
4. webcrack 自动处理(去混淆+拆模块)
5. 目标模块深入(API/密钥/算法)
6. 还原产物 → 第 13 章分析方法
100.6 检查清单
□ bundle 定位(主文件+chunk)
□ SourceMap 检查(尾注释/URL/目录枚举)
□ map 恢复源码(DevTools/工具)
□ 无 map: webpack 结构识别
□ 模块边界分割
□ webcrack 去混淆
□ 目标模块提取(API/密钥/逻辑)
□ 框架专项(Next/Vue 路由→chunk)
□ 报告: 源码恢复程度+发现
动手练习
- 用一个带 SourceMap 的测试站点(或自己 build 一个 webpack 项目带 map),完整恢复源码。
- 构建一个无 map 的混淆 bundle,用 webcrack 处理,对比恢复效果。
- 手工识别 webpack 的 chunk 注册表,找到 3 个模块的边界。
- 分析一个 Next.js 站点的 chunks 结构,画出"页面→chunk→逻辑"的映射。
深入阅读
- 仓库:
CTF-Sandbox-Orchestrator/competition-bundle-sourcemap-recovery/(bundle/sourcemap CTF 子技能) - 仓库:
CTF-Sandbox-Orchestrator/competition-bundle-sourcemap-recovery/references/bundle-sourcemap-recovery.md - 仓库:
skills/js-reverse/(第 13 章五阶段工作流) - 仓库:
CTF-Sandbox-Orchestrator/competition-template-render-path/(SSR/水合数据) - 仓库:
skills/reverse-engineering/languages-platforms.md(Electron ASAR 同思路)