Files
hello_js_reverse_skill/references/mcp-cookbook.md
T
白夜 9477d076f2 v3.3.0: 核心层回归扩容 + 案例层强化
SKILL.md:
- Phase 1-5 详细动作从 references/ 拉回核心层
- 10 个场景速查回迁
- 经验法则扩到 24 条(含环境伪装编码纪律)
- 工具名全部对齐 MCP v1.0.0 API
- 版本记录移至 README.md

cases/jsvmp-xhr-interceptor-env-emulation.md:
- 追加禁动清单(5 个禁动对象)
- 追加 UA 分支矩阵(Firefox/Chrome 必补/禁补)
- 追加 6 条踩坑记录 + env-patch 最小化原则

cases/_template.md:
- 追加禁动清单 + UA 分支矩阵可选段骨架

README.md:
- MCP 工具表对齐 v1.0.0 API
- 项目结构补充 cases/ 和完整 references/
- 追加版本记录
- 删除 skill不保存什么 段

references/:
- phase-details.md / mcp-cookbook.md / experience-rules-full.md 顶部加以SKILL.md为准提示
2026-04-19 23:23:31 +08:00

31 KiB
Raw Blame History

⚠️ v3.3.0 起,本文档的核心动作清单已回迁到 SKILL.md 核心层。 本文档保留作为深度背景参考,但以 SKILL.md 为准。如发现不一致,以 SKILL.md 为准。

MCP 工具使用手册

概述

本手册详细说明 camoufox-reverse MCP 服务器的使用方式, 提供常见逆向场景下的具体操作步骤。

工具速查表

camoufox-reverse MCP(65 个工具,v0.4.0+)

类别 工具 核心用途
浏览器 launch_browser / close_browser 启动/关闭反检测浏览器
导航 navigate / reload / go_back 页面导航
页面交互 click / type_text / wait_for 元素交互
截图 take_screenshot / take_snapshot 截图 / 无障碍树
页面信息 get_page_info / get_page_html 页面状态和 HTML
源码搜索 search_code 在所有 JS 中搜索(结构化结果,默认 max_results=50)
精确搜索 search_code(..., script_url=...) 在指定脚本中搜索(前后 3 行上下文,适合大文件)
源码获取 scripts(action='get', ...) 获取指定脚本的代码
源码保存 scripts(action='save', ...) 将脚本保存到本地文件
脚本列表 scripts(action='list') 列出页面加载的所有脚本
执行 JS evaluate_js / evaluate_js_handle 在页面执行任意 JS
加载前注入 add_init_script 页面加载前注入脚本(支持 persistent 跨导航重注入)
伪断点 set_breakpoint_via_hook 通过 Hook 设置伪断点(支持 persistent 持久化)
断点数据 get_breakpoint_data 获取伪断点捕获的数据
函数追踪 hook_function(..., mode='trace', ...) / get_trace_data 追踪函数调用(支持 persistent 跨导航持久化)
自定义 Hook hook_function 注入自定义 Hook(before/after/replace,支持 non_overridable 防覆盖)
预设 Hook inject_hook_preset 一键 Hook(xhr/fetch/crypto/websocket/debugger_bypass,默认持久化)
移除 Hook remove_hooks 移除所有 Hook(支持 keep_persistent 保留持久化 Hook)
冻结原型 hook_function(..., mode='intercept', ...) 冻结任意原型方法,防止页面 JS 覆盖 Hook
属性追踪 hook_jsvmp_interpreter(mode='proxy', trackProps=True) / get_property_access_log Proxy 级别属性访问追踪
JSVMP 插桩 hook_jsvmp_interpreter 一键插桩 JSVMP(Function.prototype.apply + 30+ 敏感属性)
JSVMP 日志 get_jsvmp_log 获取 JSVMP 日志(API 调用统计 + 属性读取摘要)
JSVMP 字符串 dump_jsvmp_strings 提取字符串数组,识别 API 名称,检测混淆模式
环境采集 compare_env 全面收集浏览器环境(navigator/screen/canvas/WebGL/Audio/timing)
网络捕获 network_capture(action='start', ...) / network_capture(action='stop') 启停网络捕获(支持 capture_body 捕获响应体)
网络请求 list_network_requests 列出捕获的请求
请求详情 get_network_request 获取请求完整信息(含响应体)
请求来源 get_request_initiator 获取请求的 JS 调用栈(改进 URL 匹配 + 诊断信息)
请求拦截 intercept_request / stop_intercept 拦截/修改/Mock 请求
Cookie cookies(action='get', ...) / cookies(action='set', ...) / delete_cookies Cookie 管理
Storage get_storage / set_storage localStorage / sessionStorage
状态管理 export_state / import_state 保存/恢复浏览器状态
控制台 get_console_logs 读取控制台输出
指纹 get_fingerprint_info 检查浏览器指纹
反检测 check_detection 测试是否被反爬识别
反调试 bypass_debugger_trap 绕过 debugger 陷阱
分发循环扫描 search_code(keyword='switch', script_url=..., context_chars=500) [v0.4.0] 定位字节码分发函数(while+switch,case 数过滤)
源码级插桩 instrumentation(action='install', ...) [v0.4.0] HTTP 层改写 VMP,每个 obj[key]/fn(args) 插入 tap(通用 VMP 利器)
插桩日志 instrumentation(action='log', ...) [v0.4.0] 拉取源码插桩日志,带 hot_keys/hot_methods/hot_functions 摘要
插桩状态 check_environment() / instrumentation(action='stop', ...) [v0.4.0] 查看/停止源码插桩
Cookie 归因 analyze_cookie_sources [v0.4.0] 融合 HTTP Set-Cookie + JS document.cookie + cookie jar
hook 重载 instrumentation(action='reload') [v0.4.0] 重载使 persistent hook 先于页面 JS 执行(+ 清日志)
运行时探针日志 get_runtime_probe_log [v0.4.0] 获取 runtime_probe 预设的广谱事件日志
预设 Hook(扩展) inject_hook_preset("cookie") / inject_hook_preset("runtime_probe") [v0.4.0] 新增两个预设
首屏注入 navigate(pre_inject_hooks=[...]) [v0.4.0] 经 about:blank 装 hook 再 goto,解决首屏挑战页

场景化操作手册

场景 1:分析数据接口的加密参数

目标:找到接口中加密参数的生成逻辑

步骤 1:启动反检测浏览器
  [camoufox-reverse] launch_browser()

步骤 2:导航到目标页面
  [camoufox-reverse] navigate(url="https://target.com")

步骤 3:确认页面加载
  [camoufox-reverse] take_screenshot() → 确认页面正常

步骤 4:开始网络捕获
  [camoufox-reverse] network_capture(action='start') <!-- v3.1.0: migrated from start_network_capture -->

步骤 5:触发数据请求(如翻页)
  [camoufox-reverse] click(selector=".next-page")
  或
  [camoufox-reverse] evaluate_js(expression="document.querySelector('.next').click()")

步骤 6:查看网络请求
  [camoufox-reverse] list_network_requests

步骤 7:获取目标请求详情
  [camoufox-reverse] get_network_request(request_id=N)
  → 记录 URL、Headers、Params、Response

步骤 8:获取请求调用栈(黄金路径)
  [camoufox-reverse] get_request_initiator(request_id=N)
  → 直接定位发起请求的 JS 函数

步骤 9:搜索加密参数
  [camoufox-reverse] search_code(keyword="参数名=")
  [camoufox-reverse] search_code(keyword="参数名")

步骤 10:读取相关源码
  [camoufox-reverse] scripts(action='get', script_url="包含加密逻辑的脚本URL") <!-- v3.1.0: migrated from get_script_source -->

步骤 11:设置伪断点验证
  [camoufox-reverse] set_breakpoint_via_hook(target_function="加密函数路径")
  触发请求 →
  [camoufox-reverse] get_breakpoint_data
  → 查看捕获的参数和返回值

目标:找到 Cookie 的生成逻辑

步骤 1:注入 Cookie Hook
  [camoufox-reverse] hook_function(
    function_path="Document.prototype.cookie",
    hook_code="console.log('[Cookie Set]', arguments[0]); console.trace('Cookie Stack');",
    position="before"
  )
  或使用预设 Hook:
  [camoufox-reverse] inject_hook_preset(preset="crypto")

步骤 2:刷新页面触发 Cookie 生成
  [camoufox-reverse] reload()

步骤 3:读取 Hook 输出
  [camoufox-reverse] get_console_logs
  → 找到 Cookie 设置记录和调用栈

步骤 4:根据调用栈定位生成函数
  [camoufox-reverse] search_code(keyword="目标函数名")
  [camoufox-reverse] scripts(action='get', script_url="...") <!-- v3.1.0: migrated from get_script_source -->

步骤 5:分析生成逻辑
  [camoufox-reverse] set_breakpoint_via_hook(target_function="cookie生成函数")
  刷新页面 →
  [camoufox-reverse] get_breakpoint_data → 查看入参和返回值
  [camoufox-reverse] hook_function(function_path="加密函数", mode='trace', log_args=true, log_return=true, log_stack=true) <!-- v3.1.0: migrated from trace_function -->
  [camoufox-reverse] get_trace_data → 查看中间值

场景 3:混淆代码分析

目标:还原混淆的 JS 代码

步骤 1:列出所有脚本
  [camoufox-reverse] scripts(action='list') <!-- v3.1.0: migrated from list_scripts -->
  → 找到可疑的混淆脚本(通常文件名无意义或体积很大)

步骤 2:保存混淆脚本到本地
  [camoufox-reverse] scripts(action='save', script_url="混淆脚本URL", save_path="./project/obfuscated.js") <!-- v3.1.0: migrated from save_script -->

步骤 3:搜索关键特征
  [camoufox-reverse] search_code(keyword="_0x")
  → 确认混淆类型(OB混淆)
  
  [camoufox-reverse] search_code(keyword="switch|while.*true")
  → 检查是否有控制流平坦化

步骤 4:在浏览器中还原字符串
  [camoufox-reverse] evaluate_js(expression="返回字符串数组的代码")
  → 获取解密后的字符串映射

步骤 5:定位关键函数
  [camoufox-reverse] search_code(keyword="encrypt|sign|md5|aes")
  → 找到加密相关代码的大致位置
  [camoufox-reverse] scripts(action='get') → 获取上下文 <!-- v3.1.0: migrated from get_script_source -->

场景 4:WASM 逆向

目标:分析 WASM 加密函数的输入输出

步骤 1:搜索 WASM 加载代码
  [camoufox-reverse] search_code(keyword="WebAssembly|.wasm|instantiate")

步骤 2:找到 WASM 文件
  [camoufox-reverse] list_network_requests
  → 找到 .wasm 文件的请求

步骤 3:分析 WASM 调用
  [camoufox-reverse] search_code(keyword="exports.|instance.exports")
  → 找到导出函数的调用代码

步骤 4:追踪输入输出
  [camoufox-reverse] set_breakpoint_via_hook(target_function="wasm导出函数调用路径")
  触发请求 →
  [camoufox-reverse] get_breakpoint_data → 查看入参和返回值

步骤 5:在浏览器中测试
  [camoufox-reverse] evaluate_js(expression="调用wasm函数并返回结果")
  → 验证 I/O 关系

场景 5:WebSocket 通信分析

目标:分析 WebSocket 消息格式和加密

步骤 1:注入 WebSocket Hook
  [camoufox-reverse] inject_hook_preset(preset="websocket")

步骤 2:读取 WS 消息日志
  [camoufox-reverse] get_console_logs
  → 获取 WS 发送/接收消息

步骤 3:搜索 WS 相关代码
  [camoufox-reverse] search_code(keyword="WebSocket|ws.send|onmessage")

步骤 4:手动发送 WS 消息
  [camoufox-reverse] evaluate_js(expression="ws.send(JSON.stringify({...}))")

场景 6:通用 JSVMP 源码级插桩(RS/Akamai/webmssdk)[v2.5.0 新增]

目标:定位 VMP 读取的环境指纹集与调用的加密原语,不依赖 VMP 具体实现

步骤 1:启动浏览器 + 开启响应体捕获
  [camoufox-reverse] launch_browser(headless=False)
  [camoufox-reverse] network_capture(action='start', capture_body=True) <!-- v3.1.0: migrated from start_network_capture -->

步骤 2:第一次导航定位 VMP 脚本
  [camoufox-reverse] navigate(url="https://target.com/")
  [camoufox-reverse] list_network_requests(resource_type="script")
  → 找最大的 JS(100KB+,通常是 sdenv-*.js / FuckCookie_*.js / webmssdk.es5.js)

步骤 3:确认是 VMP
  [camoufox-reverse] search_code(keyword='switch', script_url="https://target.com/xxx/sdenv-xxx.js", context_chars=500) <!-- v3.1.0: migrated from find_dispatch_loops -->
    min_case_count=20
  )
  → case_count > 50 基本确认是 VMP

步骤 4:装源码级插桩(核心)
  [camoufox-reverse] instrumentation(action='install', <!-- v3.1.0: migrated from instrument_jsvmp_source -->
    url_pattern="**/sdenv-*.js",
    mode="ast",       # 能联网用 ast(99% 覆盖);离线用 regex(80%)
    tag="vmp1"
  )

步骤 5:兜底 hook
  [camoufox-reverse] inject_hook_preset(preset="cookie", persistent=True)
  [camoufox-reverse] inject_hook_preset(preset="xhr", persistent=True)
  [camoufox-reverse] hook_jsvmp_interpreter(script_url="sdenv-")
  [camoufox-reverse] bypass_debugger_trap()

步骤 6:重载让插桩先于 VMP 生效
  [camoufox-reverse] instrumentation(action='reload') <!-- v3.1.0: migrated from reload_with_hooks -->

步骤 7:触发业务操作(翻页 / 登录 / 搜索)

步骤 8:读 hot_keys / hot_methods / hot_functions(30 秒读完 VMP 指纹)
  [camoufox-reverse] instrumentation(action='log', <!-- v3.1.0: migrated from get_instrumentation_log -->
    tag_filter="vmp1",
    type_filter="tap_get",    # 所有 obj[key] 读取
    limit=200
  )
  → summary.hot_keys: VMP 读了哪些属性(top 30,按频次)

  [camoufox-reverse] instrumentation(action='log', <!-- v3.1.0: migrated from get_instrumentation_log -->
    tag_filter="vmp1",
    type_filter="tap_method",  # 所有 obj.method(args) 调用
    limit=200
  )
  → summary.hot_methods: VMP 调了哪些方法(Array.prototype.join / CryptoJS.MD5 ...)

  [camoufox-reverse] instrumentation(action='log', <!-- v3.1.0: migrated from get_instrumentation_log -->
    tag_filter="vmp1",
    type_filter="tap_call",   # 所有 fn(args) 直接调用
    limit=200
  )
  → summary.hot_functions: VMP 调了哪些函数

步骤 9:Cookie 归因
  [camoufox-reverse] analyze_cookie_sources()
  → 对每个 cookie 返回 sources(http_set_cookie / js_document_cookie)
    + http_responses[].url + js_writes[].stack

步骤 10:完工清理
  [camoufox-reverse] instrumentation(action='stop', url_pattern="**/sdenv-*.js") <!-- v3.1.0: migrated from stop_instrumentation -->
  [camoufox-reverse] remove_hooks()

判定与后续策略:

hot_methods 包含 hot_keys 环境属性数 策略
CryptoJS.MD5 / SubtleCrypto.digest / btoa 少(< 15) 纯算法还原(Node.js crypto / Python hashlib)
大量自定义 fn 名 少(< 15) 提取 VMP 子片段 + vm 沙箱
CryptoJS / SubtleCrypto 多(40+) + cookie 来自 HTTP Set-Cookie jsdom 环境伪装(走路径 B)

详细方法论见 references/jsvmp-source-instrumentation.md。

场景 7:Cookie 归因分析 [v2.5.0 新增]

目标:搞清楚某个 Cookie 到底是谁写的(JS / HTTP Set-Cookie / 混合)

步骤 1:启动环境 + 开启响应体捕获 + cookie hook
  [camoufox-reverse] launch_browser(headless=False)
  [camoufox-reverse] network_capture(action='start', capture_body=True) <!-- v3.1.0: migrated from start_network_capture -->
  [camoufox-reverse] inject_hook_preset(preset="cookie", persistent=True)   # 原型链级

步骤 2:导航到目标(首屏有挑战用 pre_inject_hooks)
  [camoufox-reverse] navigate(
    url="https://target.com/",
    pre_inject_hooks=["xhr", "fetch", "cookie"]
  )

步骤 3:触发可疑 Cookie 的生成场景(刷新 / 登录 / 点业务按钮)

步骤 4:一把归因
  [camoufox-reverse] analyze_cookie_sources(name_filter="acw_tc|NfBCSins|x-bogus")
  → 返回:
    {
      "cookies": {
        "acw_tc": {
          "sources": ["http_set_cookie"],
          "first_set_ts": ...,
          "http_responses": [{"url": ".../challenge", "ts": ..., "header": "acw_tc=...; path=/"}],
          "js_writes": [],
          "current_value": "..."
        },
        "x-bogus-js": {
          "sources": ["js_document_cookie"],
          "first_set_ts": ...,
          "http_responses": [],
          "js_writes": [{"value": "x-bogus-js=...", "stack": "...encrypt@webmssdk.es5.js:..."}],
          "current_value": "..."
        }
      },
      "total_cookies": 2
    }

步骤 5:按归因结果进一步分析
  a. 纯 http_set_cookie → 看 http_responses[].url 是哪个接口,它的请求体里有什么签名参数
     → 用场景 1 分析那个接口的加密参数
  b. 纯 js_document_cookie → 看 js_writes[].stack 定位写入函数,search_code 打开源码
  c. 两者都有 → 两步都做(JS 算 token POST 给服务端,服务端 Set-Cookie 回来)

关键洞察:

对于RS、Akamai 这类"JS 算 token、服务端 Set-Cookie"的混合模式,单纯 hook_function(Document.prototype.cookie) 是抓不到最终 cookie 写入的——因为它是 HTTP header 写的,不经过 JS。analyze_cookie_sources 的价值就是 30 秒内消除这个盲区。

高级技巧

使用 hook_function(mode='trace') 自动记录函数调用

[camoufox-reverse] hook_function( <!-- v3.1.0: migrated from trace_function -->
    function_path="window.encrypt",
    mode='trace',
    log_args=true,
    log_return=true,
    log_stack=true,
    max_captures=50,
    persistent=True          → 跨导航持久化,页面刷新/跳转后自动重注入
)

→ 每次 encrypt 被调用时自动记录参数、返回值和调用栈,不暂停执行 → get_trace_data 会自动合并页面数据和 Python 端持久化数据

使用 inject_hook_preset 一键 Hook

默认 persistent=True(持久化,跨导航自动重注入):

[camoufox-reverse] inject_hook_preset(preset="xhr")              → Hook 所有 XHR 请求
[camoufox-reverse] inject_hook_preset(preset="fetch")             → Hook 所有 fetch 请求
[camoufox-reverse] inject_hook_preset(preset="crypto")            → Hook btoa/atob/JSON.stringify
[camoufox-reverse] inject_hook_preset(preset="websocket")         → Hook WebSocket 消息
[camoufox-reverse] inject_hook_preset(preset="debugger_bypass")   → 绕过反调试

使用 hook_function 自定义 Hook

[camoufox-reverse] hook_function(
    function_path="XMLHttpRequest.prototype.open",
    hook_code="console.log('[XHR]', arguments[0], arguments[1])",
    position="before",
    non_overridable=True     → 防覆盖:Object.defineProperty 冻结 + toString 伪装 native code
)

→ 在 XHR.open 调用前输出请求方法和 URL,即使页面 JS 尝试覆盖也不会丢失

使用 hook_function(mode='intercept') 防止 Hook 被覆盖

[camoufox-reverse] hook_function(className="XMLHttpRequest", methodName="send", mode='intercept') <!-- v3.1.0: migrated from freeze_prototype -->

→ 冻结原型方法(configurable:false + writable:false),防止 JSVMP 等覆盖你的 Hook

使用 JSVMP 专项工具

[camoufox-reverse] hook_jsvmp_interpreter        → 一键插桩 Function.prototype.apply + 30+ 敏感属性
[camoufox-reverse] dump_jsvmp_strings             → 提取字符串数组,识别 API 名称
  触发操作...
[camoufox-reverse] get_jsvmp_log                  → 获取 API 调用统计 + 属性读取摘要
[camoufox-reverse] compare_env                    → 收集完整浏览器环境(补环境基准线)

transparent 模式示例(v0.5.0,v2.6.0 吸收)

# 签名型反爬上优先这样用:只替换 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 不能用的场合(签名型反爬)

使用属性访问追踪

[camoufox-reverse] hook_jsvmp_interpreter(mode='proxy', trackProps=True, target_expression="navigator") <!-- v3.1.0: migrated from trace_property_access -->
  触发操作...
[camoufox-reverse] get_property_access_log        → 查看 navigator 的哪些属性被读取

→ 精确发现 JSVMP 或签名逻辑读取了哪些环境属性

使用 search_code(..., script_url=...) 精确搜索大文件

[camoufox-reverse] search_code(keyword="sign|token|encrypt", script_url=3) <!-- v3.1.0: migrated from search_code_in_script -->

→ 在指定脚本中搜索,返回前后 3 行上下文,适合 200KB+ 的 JSVMP 文件

使用 add_init_script 进行预分析

[camoufox-reverse] add_init_script(script=`
    const knownGlobals = new Set(Object.keys(window));
    setInterval(() => {
        const newGlobals = Object.keys(window).filter(k => !knownGlobals.has(k));
        if (newGlobals.length > 0) {
            console.log('[Monitor] 新全局变量:', newGlobals);
            newGlobals.forEach(k => knownGlobals.add(k));
        }
    }, 1000);
`, persistent=True)         → 跨导航持久化

使用 evaluate_js 提取运行时数据

[camoufox-reverse] evaluate_js(expression=`
    JSON.stringify(document.cookie.split('; ').reduce((obj, pair) => {
        const [k, v] = pair.split('=');
        obj[k] = v;
        return obj;
    }, {}))
`)

使用 intercept_request 拦截/修改请求

[camoufox-reverse] intercept_request(url_pattern="**/api/data*", action="log")     → 仅记录
[camoufox-reverse] intercept_request(url_pattern="**/ads/*", action="block")       → 屏蔽广告
[camoufox-reverse] intercept_request(url_pattern="**/api/*", action="modify", modify_headers={"X-Custom": "test"})
[camoufox-reverse] intercept_request(url_pattern="**/api/*", action="mock", mock_response={"status": 200, "body": "{\"ok\":1}"})

使用源码级插桩(v2.5.0 新增,通用 VMP 利器)

# 1. 先确认是不是 VMP(case_count > 50 基本是)
[camoufox-reverse] search_code(keyword='switch', script_url="https://target.com/sdenv-xxx.js", context_chars=500) <!-- v3.1.0: migrated from find_dispatch_loops -->

# 2. 装插桩(AST 模式优先,需 CDN;regex 模式兜底)
[camoufox-reverse] instrumentation(action='install', <!-- v3.1.0: migrated from instrument_jsvmp_source -->
    url_pattern="**/sdenv-*.js",    # glob 模式匹配多 hash 版本
    mode="ast",                      # 或 "regex"
    tag="vmp1",                      # 区分多 VMP 的标签
    rewrite_member_access=True,      # 改写每个 obj[key]
    rewrite_calls=True,              # 改写每个 fn(args) / obj.method(args)
    max_rewrites=5000,               # 单文件改写上限
    cache_rewritten=True             # 缓存改写后源码
)

# 3. 装完后必须重载让插桩生效
[camoufox-reverse] instrumentation(action='reload') <!-- v3.1.0: migrated from reload_with_hooks -->

# 4. 触发操作后读日志
[camoufox-reverse] instrumentation(action='log', tag_filter="vmp1", type_filter="tap_get", limit=200) <!-- v3.1.0: migrated from get_instrumentation_log -->
  → summary.hot_keys 是 VMP 读取的环境属性 top 30(指纹学习金矿)

[camoufox-reverse] instrumentation(action='log', tag_filter="vmp1", type_filter="tap_method", limit=200) <!-- v3.1.0: migrated from get_instrumentation_log -->
  → summary.hot_methods 是 VMP 调用的方法 top 30(ObjectType.methodName 格式)

# 5. 查看插桩状态
[camoufox-reverse] check_environment() <!-- v3.1.0: migrated from get_instrumentation_status -->

# 6. 完工移除
[camoufox-reverse] instrumentation(action='stop', url_pattern="**/sdenv-*.js") <!-- v3.1.0: migrated from stop_instrumentation -->
[camoufox-reverse] instrumentation(action='stop')    # 不传参数 = 全部停止 <!-- v3.1.0: migrated from stop_instrumentation -->

与 hook_jsvmp_interpreter 的分工:

工具 能看到 看不到
hook_jsvmp_interpreter VMP 通过 Function.prototype.apply/call/bind 或 Reflect.* 调子函数,读全局对象属性(Proxy) VMP 在 switch/case 内部直接 obj[key] / fn(args) 的调用
instrumentation(action='install', ...) 每一次 member access + 每一次函数调用,无论是否通过可 hook API 不跨脚本(只改写指定 url_pattern 的那个文件)
建议:两者同时开,互相校验

mode="ast" 的 v0.5.0 变化(v2.6.0 吸收)

# 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 instrumentation(action='install', url_pattern="**/sdenv-*.js", <!-- v3.1.0: migrated from instrument_jsvmp_source -->
    mode="ast",                  # 默认,走 MCP 侧 esprima
    tag="sdenv",
    fallback_on_error=True,      # 新参数:esprima 挂就回落 regex
)

# 查看实际走了哪条路径
status = await check_environment() <!-- v3.1.0: migrated from get_instrumentation_status -->
# status["active_patterns"][0]["last_mode_used"] == "ast" (正常)
#   or "regex (fallback)" (esprima 对该 VMP 的语法支持不全)
#   or "ast_page" (你显式用了 deprecated 模式)

新增取值 mode="ast_page":

# 仅用于 A/B 对比 v0.4.x 的旧页面内 Acorn 实现,deprecated
# 生产不要用,挑战页会因 CDN 被拦静默失败
await instrumentation(action='install', url_pattern="**/vmp.js", mode="ast_page") <!-- v3.1.0: migrated from instrument_jsvmp_source -->
# 1. 前置条件:网络抓包 + cookie hook 同时开
[camoufox-reverse] network_capture(action='start', capture_body=True) <!-- v3.1.0: migrated from start_network_capture -->
[camoufox-reverse] inject_hook_preset(preset="cookie", persistent=True)

# 2. 触发场景

# 3. 一键归因
[camoufox-reverse] analyze_cookie_sources(name_filter="ttwid|msToken|acw_tc")

返回字段:
  cookies[name].sources: ["http_set_cookie" | "js_document_cookie"]   # 可能两者都有
  cookies[name].first_set_ts: 首次观察到的毫秒时间戳
  cookies[name].http_responses: [{url, ts, header}]                    # HTTP 写入来源
  cookies[name].js_writes: [{value, stack, ts}]                        # JS 写入来源(含调用栈)
  cookies[name].current_value: 当前 jar 中的值

使用 runtime_probe 做低开销广谱观察(v2.5.0 新增)

# runtime_probe 是 jsvmp_hook 的轻量版:不装 Proxy,只 override 具体热点 API
[camoufox-reverse] inject_hook_preset(preset="runtime_probe", persistent=True)

# 触发操作
[camoufox-reverse] get_runtime_probe_log(type_filter="xhr_send", limit=100)
[camoufox-reverse] get_runtime_probe_log(type_filter="canvas_toDataURL", limit=50)   # canvas 指纹检测
[camoufox-reverse] get_runtime_probe_log(type_filter="nav_read", limit=100)          # navigator 读取
[camoufox-reverse] get_runtime_probe_log(type_filter="addEventListener", limit=100)  # 鼠标/键盘检测

返回 by_type 字段自动聚合各事件类型的总数,便于快速画出"这个页面都在观察什么"。

使用 pre_inject_hooks 解决首屏挑战页(v2.5.0 新增)

# RS 412 / Akamai 首包检测场景:
# 普通 navigate → launch_browser → navigate → 装 hook
# 但此时 challenge JS 已经跑完了,hook 完全漏掉第一次 VMP 执行

# 正确做法:走 about:blank 先装 hook 再 goto
[camoufox-reverse] navigate(
    url="https://target.com/",
    wait_until="networkidle",
    pre_inject_hooks=["xhr", "fetch", "cookie", "jsvmp_probe"],   # 先装这些
    via_blank=True,                                                # 强制经 about:blank
    collect_response_chain=True                                    # 记录重定向链
)

# 返回:
#   initial_status: 首次响应状态(可能是 412)
#   final_status:   最终状态(challenge 过后的 200)
#   redirect_chain: [{url, status, ts}, ...] 整条重定向链
#   hooks_injected: 实际装上的 hook 名列表
#   warnings:       装 hook 失败等非致命问题

camoufox-reverse MCP 工具分类总览(65 个,v0.4.0+)

类别 工具 说明
浏览器生命周期 launch_browser close_browser 启动/关闭 Camoufox
页面导航 navigate reload go_back 导航控制
页面交互 click type_text wait_for UI 自动化
页面状态 get_page_info take_screenshot take_snapshot get_page_html 页面信息
源码分析 scripts(action='list') scripts(action='get', ...) search_code search_code(..., script_url=...) scripts(action='save', ...) JS 逆向核心
JS 执行 evaluate_js evaluate_js_handle add_init_script 代码执行(支持持久化)
调试 set_breakpoint_via_hook get_breakpoint_data get_console_logs 伪断点调试(支持持久化)
Hook hook_function(..., mode='trace', ...) get_trace_data hook_function inject_hook_preset remove_hooks hook_function(..., mode='intercept', ...) 函数 Hook(支持持久化 + 防覆盖)
属性追踪 hook_jsvmp_interpreter(mode='proxy', trackProps=True) get_property_access_log Proxy 级别属性访问监控
JSVMP 专项 hook_jsvmp_interpreter get_jsvmp_log dump_jsvmp_strings compare_env JSVMP 虚拟机保护分析
网络 network_capture(action='start', ...) network_capture(action='stop') list_network_requests get_network_request get_request_initiator intercept_request stop_intercept 网络分析(支持响应体捕获)
存储 cookies(action='get', ...) cookies(action='set', ...) delete_cookies get_storage set_storage export_state import_state 状态管理
反检测 get_fingerprint_info check_detection bypass_debugger_trap 指纹与反检测
源码级插桩 instrumentation(action='install', ...) instrumentation(action='log', ...) check_environment() instrumentation(action='stop', ...) search_code(keyword='switch', script_url=..., context_chars=500) [v0.4.0] 通用 JSVMP 逆向利器
Cookie 归因 analyze_cookie_sources [v0.4.0] HTTP Set-Cookie + JS 写入融合分析
导航增强 navigate(pre_inject_hooks) instrumentation(action='reload') get_runtime_probe_log [v0.4.0] 首屏挑战/hook 重注入/运行时探针