feat(v2.6.0): signature-based anti-bot compatibility + MCP v0.5.0 alignment

- Add top-level chapter: anti-bot type classification (signature/behavioral/obfuscation)
- Add observer effect warning for pre_inject_hooks on signature-based anti-bot
- Add hook_jsvmp_interpreter mode parameter (proxy/transparent)
- Update instrument_jsvmp_source AST mode: MCP-side esprima (zero CDN dependency)
- Add fallback_on_error parameter and last_mode_used status field
- Add four-axe applicability labels per anti-bot type
- Rewrite scenario 9 (anti-detection sites) by anti-bot type
- Add scenario 11 signature-type pre-check
- Add observer effect troubleshooting section
- Add experience rules 28-32
- Add AST health diagnostics to jsvmp-source-instrumentation.md
- Add transparent mode examples to mcp-cookbook.md
- Add anti-bot type column to cases/README.md
- Create CHANGELOG_v2.6.0.md
This commit is contained in:
白夜
2026-04-18 01:26:56 +08:00
parent 25fb9513e4
commit 8cbaa8b704
8 changed files with 409 additions and 20 deletions
+44
View File
@@ -507,6 +507,50 @@ MCP 操作:
---
## 前置判断(v2.6.0 新增):先识别 JSVMP 所在反爬类型
在选路径 A / B 之前,先判断 JSVMP 的反爬类型:
```
navigate(url) 不加任何 hook 观察 redirect_chain
│
├─ 反复 412 后才到 200 → 签名型 JSVMP(瑞数/Akamai)
│ └─ 走"签名型专属路径"(见下文)
│
├─ 直接 200 但主请求链带签名参数 → 行为型 JSVMP(TikTok/极验)
│ └─ 按原路径 A / 路径 B 决策树选择
│
└─ 直接 200 无签名参数 → 非 JSVMP 或 VMP 已被跳过
└─ 回 Phase 2.2 常规混淆分析
```
### 签名型 JSVMP 专属路径(v2.6.0 新增)
签名型 JSVMP 与原路径 A / B 的决策树**不适用**,因为:
- 路径 A 的前三板斧(Hook/插桩/日志)会破坏签名
- 路径 B 的 jsdom 环境伪装成本高(58+ 项修复)
签名型 JSVMP 推荐走的路:
```
1. instrument_jsvmp_source(mode="ast", tag="...") (第四板斧)
2. reload_with_hooks() 让插桩后的 VMP 跑完挑战
3. get_instrumentation_log(tag_filter, type_filter="tap_get")
4. 基于 hot_keys 补最小环境,在 jsdom 或纯 Python 侧独立跑
(此时 jsdom 补环境的粒度比路径 B 小得多,只补 hot_keys 显示的属性)
```
源码级插桩失败才回落:
```
A. hook_jsvmp_interpreter(mode="transparent") 仅 prototype getter 替换
- 对签名型大多数情况安全
- 极严格反爬仍能识别 getter identity 变化,此时真的只能走路径 B 全量 jsdom 伪装
B. 路径 B 完整 jsdom 环境伪装(六步法)
- 最重但最稳,是最后的兜底
```
---
## 还原策略决策(v2.5.0 扩充源码级插桩分支)
```
@@ -90,6 +90,13 @@ __mcp_tap_call(fn, null, [args[0], args[1], ...], 'vmp1');
- 需要 `hot_methods` / `hot_functions` 数据(只有 AST 模式会生成)
- **失败回退**:AST 解析失败时(例如脚本有语法错误或 Acorn 版本不支持的语法),`instrument_jsvmp_source` 会自动 pass-through 源码不变,并在 console 记 warn
> **v0.5.0 变化**:`mode="ast"` 的实现从 v0.4.x 的"页面内加载 acorn CDN"改为
> **MCP 侧 esprima-python 解析**。这意味着:
> - 挑战页(瑞数 412、Akamai sensor_data 挑战等)上 AST 模式**能用了**(旧实现因 CDN 被挑战拦住会静默失败)
> - 零 JS 依赖,`instrument_jsvmp_source` 的 AST 模式现在**应成为默认选择**
> - 新增 `fallback_on_error=True`,esprima 解析失败时自动回落 regex
> - 旧的 "ast_page" 模式保留但标注为 deprecated,仅做 A/B 对比用
### 2.3 选择建议
| 情况 | 选 | 原因 |
@@ -102,6 +109,27 @@ __mcp_tap_call(fn, null, [args[0], args[1], ...], 'vmp1');
---
## AST 模式健康诊断(v2.6.0 新增)
启用 `instrument_jsvmp_source(mode="ast")` 后,通过 `get_instrumentation_status()` 的 `active_patterns[i].last_mode_used` 字段判断实际走了哪条路径:
| `last_mode_used` | 含义 | 动作 |
|---|---|---|
| `"ast"` | MCP 侧 esprima 成功,全量 AST 改写 | 正常,继续 |
| `"regex"` | 你显式指定了 `mode="regex"` | 正常,继续 |
| `"regex (fallback)"` | `mode="ast"` 但 esprima 解析失败,自动回落 regex | **警告**:看下文 |
| `"ast_page"` | 走的是 deprecated 的页面内 Acorn 实现 | 迁到 `"ast"`,除非你在做 A/B |
`"regex (fallback)"` 持续出现时:
1. 先 `get_console_logs` 里搜 `[INSTRUMENT] AST parse failed`,看具体报错
2. 如果是 ES2022+ 的 private field / static block / top-level await 等新语法 → 手动 `mode="regex"`(~80% 覆盖)或 `mode="transparent"`(runtime 观察)兜底
3. 如果是 `SyntaxError: Unexpected token` 开头 → 可能 JS 被加了 BOM 或非标准前缀,可以本地用 `curl` 下来手动检查首 100 字节
一般来说,瑞数 sdenv*.js / Akamai acmescripts*.js / webmssdk 都能被 esprima 解析。如果出现持续 fallback,报告给 MCP 仓库 issue 区。
---
## 3. 黄金 8 步流程
> 这是面向瑞数 5/6、Akamai sensor_data、webmssdk、obfuscator.io 的通用流程。照抄 `Actions` 段即可,执行方需要替换的只有 `url_pattern` 和 `script_url`。
+50
View File
@@ -404,6 +404,30 @@
[camoufox-reverse] compare_env → 收集完整浏览器环境(补环境基准线)
```
#### transparent 模式示例(v0.5.0,v2.6.0 吸收)
```python
# 签名型反爬上优先这样用:只替换 prototype getter,不装 Proxy 不改 Function.prototype
await hook_jsvmp_interpreter(
script_url="sdenv",
persistent=True,
mode="transparent", # 关键
# track_calls / track_props / track_reflect / proxy_objects 在 transparent 下被忽略
max_entries=10000,
)
# 效果:window.__mcp_jsvmp_log 仍然有日志,但每条是 {type: "transparent_get", owner, key, value}
# 不会出现 proxy_get / fn_apply / reflect_get 等 proxy 模式专属类型
# 对应的 pre-inject 别名:
await navigate(url, pre_inject_hooks=["jsvmp_probe_transparent"])
```
**transparent 模式的观察口径**:
- ✅ 会记录:navigator.userAgent / screen.width / document.cookie(读) / location.href 等 prototype 级 getter
- ❌ 不会记录:Function.prototype.apply 调用、Reflect.get/set、navigator.plugins[0].name(深层属性)、navigator.hardwareConcurrency(getter 在不同浏览器可能不是 prototype 级)
- **口径比 proxy 小**,所以只用于 proxy 不能用的场合(签名型反爬)
### 使用属性访问追踪
```
@@ -499,6 +523,32 @@
| `instrument_jsvmp_source` | 每一次 member access + 每一次函数调用,无论是否通过可 hook API | 不跨脚本(只改写指定 url_pattern 的那个文件) |
| **建议**:两者同时开,互相校验 | | |
#### mode="ast" 的 v0.5.0 变化(v2.6.0 吸收)
```python
# v2.5.0 / MCP v0.4.x: mode="ast" 会在页面里注入 acorn CDN script tag
# v2.6.0 / MCP v0.5.0: mode="ast" 在 MCP 进程里用 esprima-python 解析,零页面依赖
await instrument_jsvmp_source(
"**/sdenv-*.js",
mode="ast", # 默认,走 MCP 侧 esprima
tag="sdenv",
fallback_on_error=True, # 新参数:esprima 挂就回落 regex
)
# 查看实际走了哪条路径
status = await get_instrumentation_status()
# status["active_patterns"][0]["last_mode_used"] == "ast" (正常)
# or "regex (fallback)" (esprima 对该 VMP 的语法支持不全)
# or "ast_page" (你显式用了 deprecated 模式)
```
**新增取值 mode="ast_page"**:
```python
# 仅用于 A/B 对比 v0.4.x 的旧页面内 Acorn 实现,deprecated
# 生产不要用,挑战页会因 CDN 被拦静默失败
await instrument_jsvmp_source("**/vmp.js", mode="ast_page")
```
### 使用 Cookie 归因分析(v2.5.0 新增)
```