JSHook MCP 使用 SOP

下载 .md

JSHook MCP 使用 SOP

概述

jshookmcp (npx -y @jshookmcp/jshook@latest) — MCP协议服务器,暴露174~387个工具覆盖浏览器/CDP/逆向/反混淆/网络分析。非GA原生工具,通过code_run启动进程+JSON-RPC stdio通信临时调用。

启动

环境变量(关键!)

变量 说明
MCP_TOOL_PROFILE workflow(推荐) / full / search 工具集大小,不是 JSHOOK_BASE_PROFILE
MCP_TRANSPORT stdio(默认) / http 传输模式。HTTP模式在Win下需处理好Accept头(406易出错)

stdio 启动(推荐)

import subprocess, json, time, threading

proc = subprocess.Popen(
    ['npx.cmd', '-y', '@jshookmcp/jshook@latest'],
    env={'MCP_TOOL_PROFILE': 'workflow'},
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
time.sleep(5)  # 等启动

MCP 通信协议

JSON-RPC 2.0 over stdio

  • 请求: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}} + \n
  • 响应: 单行JSON
  • 不要用 select.select (Windows不支持pipe的select)! 用readline()或threading读

关键坑:reader线程

buf = []
def reader():
    while True:
        line = proc.stdout.readline()
        if not line: break
        buf.append(line.decode().strip())

def mcp(method, params=None, timeout=25):
    msg = {"jsonrpc":"2.0","id":1,"method":method}
    if params: msg["params"] = params
    proc.stdin.write((json.dumps(msg) + "\n").encode())
    proc.stdin.flush()
    deadline = time.time() + timeout
    while time.time() < deadline:
        for i, item in enumerate(buf):
            try:
                resp = json.loads(item)
                buf.pop(i)
                return resp
            except: pass
        time.sleep(0.1)
    raise TimeoutError(f"Timeout: {method}")

initialize 参数

mcp("initialize", {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {"name": "test", "version": "1.0"}  # version是string, 非int!
})

工具架构(两层)

第一层: 发现工具 (workflow profile 下直接可调)

方法 用途
tools/list 列出所有已激活工具及其inputSchema
tools/call 调用工具: {"name":"xxx", "arguments":{...}}

第二层: jshook的元工具(search profile 下必须用)

工具 用途
search_tools(query, top_k?) 按关键词搜索可用工具
describe_tool(name) 查工具详情和参数
activate_tools(names[]) 激活指定工具
activate_domain(domain, ttlMinutes?) 激活整个域的工具
call_tool(name, args?) 调用已激活的工具
deactivate_tools(names[]) 释放工具释放上下文

workflow profile 下可直接 tools/call 调用工具,跳过元工具层

实战验证过的工具

⭐⭐⭐⭐⭐ 最有用

工具 实测 说明
search_in_scripts 在已收集的JS中搜关键词,返回上下文(逆向神器)
page_evaluate 在页面执行JS,参数名是code不是expression
page_navigate 导航到URL,返回页面标题
browser_launch CDP桥接到已有浏览器(wsEndpoint参数)

⭐⭐⭐⭐ 有用

工具 实测 说明
browser_list_tabs 列出所有CDP标签页
network_enable 开启网络监控(需新导航才捕获)
browser_list_cdp_targets 列出CDP targets
page_inject_script 注入JS到页面
http_plain_request 直接HTTP请求(CloudFlare下受限)

⭐⭐⭐ 有限

工具 实测 问题
collect_code ⚠️ 需url参数,大文件超时
deobfuscate ⚠️ >100KB JS 超时
network_get_requests ⚠️ CDP session不同步,需先导航
extract_function_tree ⚠️ 需scriptId/functionName
detect_obfuscation ⚠️ 参数路径问题

典型工作流

流程1: JS逆向/找API端点

1. page_navigate → dammba.com
2. page_evaluate → fetch(app.js) → 获取完整JS
3. search_in_scripts → 搜 action/ api/ down/ pay/ ajax
4. page_evaluate → 直接调 admin-ajax.php 试action

流程2: 网络抓包

1. browser_launch(wsEndpoint) → 连Edge
2. page_navigate → 目标URL
3. network_enable → 开监控
4. 等几秒 → network_get_requests

注意: network_enable必须在目标页面加载前打开,否则捕获不到

流程3: CDP桥接

# 获取Edge WS端点
info = json.loads(urllib.request.urlopen("http://127.0.0.1:9223/json/version").read())
ws = info["webSocketDebuggerUrl"]
# 传给jshook
mcp("tools/call", {"name":"browser_launch", "arguments":{"wsEndpoint": ws}})

避坑清单

1. 环境变量

  • JSHOOK_BASE_PROFILE=search不生效(变量名错误)
  • MCP_TOOL_PROFILE=workflow → 174工具

2. Windows stdio

  • select.select([proc.stdout])OSError(Windows pipe不支持select)
  • threading + readline + list buf

3. HTTP transport

  • ❌ HTTP 406 Not Acceptable(MCP HTTP transport在Win下有兼容问题)
  • ✅ 用默认stdio

4. page_evaluate

  • ❌ 参数名 expression → 报错
  • ✅ 参数名 code

5. browser_launch

  • ❌ 传 debugUrl → 报错
  • ✅ 传 wsEndpoint(CDP WebSocket URL)
  • ✅ 或传 autoConnect: true 自动发现

6. 进程管理

  • jshook用Node.js (npx),启动约5秒
  • Windows上 DETACHED_PROCESS + CREATE_NO_WINDOW 可后台运行
  • stdin EOF 会导致jshook退出 → 用 DEVNULL 或保持pipe打开

7. CloudFlare

  • jshook的 http_plain_request 直接请求会被CloudFlare拦截(403)
  • 必须在浏览器上下文中用 page_evaluate + fetch 绕过

工具域一览 (workflow profile, 174 tools)

browser_   (15) 浏览器/CDP操控: launch, list_tabs, navigate, evaluate, inject...
network_   (16) 网络监控: enable, get_requests, intercept, http_request_build...
deobfuscate (1) JS反混淆 + detect_obfuscation, js_deobfuscate_jsvmp/pipeline...
v8_         (8) V8堆分析: heap_snapshot_capture/analyze/diff, object_inspect...
binary_     (4) 二进制分析: detect_format, entropy_analysis, encode/decode...
stealth_    (5) 隐身: inject, set_user_agent, captcha_detect...
collect_    (2) 代码收集: collect_code, collect_pages...
js_         (4) JS深度分析: bundle_search, bundle_extract, solve_constraints...
api_        (1) api_probe_batch
breakpoint  (1) breakpoint
blackbox_   (3) blackbox_add/common/list

document_start 首包捕获门禁

Network 先启用 + new-document 注入 + reload/导航后读取 window.__gaTelemetry

realm 覆盖边界(R161/R166本地实测)

  • Page.addScriptToEvaluateOnNewDocument 可覆盖 main window 与新建 same-origin iframe;读取 iframe 遥测需按 frame execution context/同源消息分别汇总,不能只看顶层 window.__gaTelemetry
  • dedicated worker 不会自动获得页面级 new-document hook:若服务端/Network 已见 worker 请求但 JS telemetry 为 0,不要判定无请求,先按 worker realm 漏捕处理。
  • 目标参数疑似在 worker 内生成时,改用 CDP Target auto-attach/worker target 注入、Worker 构造器改写,或 Network+Debugger 旁路;未覆盖 worker 前不得宣称 JS Hook 全覆盖。
  • same-origin classic worker 可用 Worker 构造器改写为同源 wrapper URL:wrapper 先装 telemetry hook,再 importScripts(originalUrl);worker telemetry 用 worker 自身 postMessage 回传。
  • 不要用 Blob wrapper 承载原 worker 入口:会把 worker 内相对 URL 基准改为 blob:,破坏 /api 等相对 fetch/XHR;page target 的 CDP Network 也不等于 worker 网络全量,需服务端日志或 worker target 对照。

评论(0)

登录 后可发表评论。

暂无评论。