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:
@@ -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`。
|
||||
|
||||
@@ -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 新增)
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user