Files
hello_js_reverse_skill/references/mcp-cookbook.md
T
白夜 fb14cf7916 refactor: 将文件从子目录提升到仓库根目录
所有文件从 hello_js_reverse_skill/ 子目录移至仓库根目录,
使项目结构更清晰,便于作为 Skill 直接引用。

Made-with: Cursor
2026-03-18 22:55:27 +08:00

265 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MCP 工具使用手册
## 概述
本手册详细说明 `js-reverse` 和 `chrome-devtools` 两个 MCP 服务器的协作使用方式,
提供常见逆向场景下的具体操作步骤。
## 工具速查表
### js-reverse MCP(逆向分析核心)
| 类别 | 工具 | 核心用途 |
|------|------|---------|
| **源码搜索** | `search_in_sources` | 在所有 JS 中搜索关键词 |
| **源码获取** | `get_script_source` | 获取指定脚本的代码片段 |
| **源码保存** | `save_script_source` | 将脚本保存到本地文件 |
| **脚本列表** | `list_scripts` | 列出页面加载的所有脚本 |
| **断点设置** | `set_breakpoint_on_text` | 按代码文本设置断点 |
| **XHR 断点** | `break_on_xhr` | 在 XHR 请求时暂停 |
| **函数追踪** | `trace_function` | 追踪函数调用,记录参数 |
| **暂停信息** | `get_paused_info` | 获取断点处的栈和变量 |
| **单步调试** | `step_into/over/out` | 单步执行 |
| **脚本注入** | `inject_before_load` | 页面加载前注入 JS |
| **脚本执行** | `evaluate_script` | 在页面执行 JS |
| **网络请求** | `list_network_requests` | 列出网络请求 |
| **请求详情** | `get_network_request` | 获取请求完整信息 |
| **请求来源** | `get_request_initiator` | 获取请求的 JS 调用栈 |
| **WebSocket** | `list_websocket_connections` | 列出 WS 连接 |
| **WS 分析** | `analyze_websocket_messages` | 分析 WS 消息模式 |
| **控制台** | `list_console_messages` | 读取控制台输出 |
### chrome-devtools MCP(浏览器自动化)
| 类别 | 工具 | 核心用途 |
|------|------|---------|
| **页面管理** | `new_page` / `navigate_page` / `close_page` | 页面操作 |
| **UI 交互** | `click` / `fill` / `type_text` / `press_key` | 元素交互 |
| **DOM 快照** | `take_snapshot` | 获取页面文本结构 |
| **截图** | `take_screenshot` | 页面截图 |
| **脚本执行** | `evaluate_script` | 执行 JS |
| **设备模拟** | `emulate` | 模拟 UA/视口/网络 |
| **网络请求** | `list_network_requests` / `get_network_request` | 请求监控 |
| **等待** | `wait_for` | 等待文本出现 |
| **对话框** | `handle_dialog` | 处理弹窗 |
## 场景化操作手册
### 场景 1:分析数据接口的加密参数
**目标**:找到接口中加密参数的生成逻辑
```
步骤 1:打开目标页面
[chrome-devtools] new_page(url="https://target.com")
步骤 2:获取页面结构
[chrome-devtools] take_snapshot() → 确认页面正常加载
步骤 3:触发数据请求(如翻页)
[chrome-devtools] click(uid="翻页按钮的uid")
或
[chrome-devtools] evaluate_script(function="document.querySelector('.next').click()")
步骤 4:查看网络请求
[js-reverse] list_network_requests(resourceTypes=["XHR","Fetch"])
步骤 5:获取目标请求详情
[js-reverse] get_network_request(reqid=目标请求ID)
→ 记录 URL、Headers、Params、Response
步骤 6:获取请求调用栈
[js-reverse] get_request_initiator(requestId=目标请求ID)
→ 找到发起请求的 JS 函数
步骤 7:搜索加密参数
[js-reverse] search_in_sources(query="参数名=")
[js-reverse] search_in_sources(query="参数名")
步骤 8:读取相关源码
[js-reverse] get_script_source(url="包含加密逻辑的脚本URL", startLine=X, endLine=Y)
步骤 9:设置断点验证
[js-reverse] set_breakpoint_on_text(text="加密函数调用")
触发请求 →
[js-reverse] get_paused_info(includeScopes=true)
→ 查看变量值确认加密逻辑
```
### 场景 2:动态 Cookie 逆向
**目标**:找到 Cookie 的生成逻辑
```
步骤 1:注入 Cookie Hook
[js-reverse] inject_before_load(script="Cookie setter Hook 代码")
步骤 2:刷新页面触发 Cookie 生成
[js-reverse] navigate_page(type="reload")
步骤 3:读取 Hook 输出
[js-reverse] list_console_messages(types=["log"])
→ 找到 Cookie 设置记录和调用栈
步骤 4:根据调用栈定位生成函数
[js-reverse] search_in_sources(query="目标函数名")
[js-reverse] get_script_source(url="...", startLine=X, endLine=Y)
步骤 5:分析生成逻辑
[js-reverse] set_breakpoint_on_text(text="cookie生成代码片段")
刷新页面 →
[js-reverse] get_paused_info → 查看入参
[js-reverse] step_into → 进入加密函数
[js-reverse] get_paused_info → 查看中间值
```
### 场景 3:混淆代码分析
**目标**:还原混淆的 JS 代码
```
步骤 1:列出所有脚本
[js-reverse] list_scripts()
→ 找到可疑的混淆脚本(通常文件名无意义或体积很大)
步骤 2:保存混淆脚本到本地
[js-reverse] save_script_source(url="混淆脚本URL", filePath="./project/obfuscated.js")
步骤 3:搜索关键特征
[js-reverse] search_in_sources(query="_0x", urlFilter="混淆脚本URL")
→ 确认混淆类型(OB混淆)
[js-reverse] search_in_sources(query="switch|while.*true", urlFilter="混淆脚本URL")
→ 检查是否有控制流平坦化
步骤 4:在浏览器中还原字符串
[js-reverse] evaluate_script(function="返回字符串数组的代码")
→ 获取解密后的字符串映射
步骤 5:定位关键函数
[js-reverse] search_in_sources(query="encrypt|sign|md5|aes", urlFilter="混淆脚本URL")
→ 找到加密相关代码的大致位置
[js-reverse] get_script_source → 获取上下文
```
### 场景 4:WASM 逆向
**目标**:分析 WASM 加密函数的输入输出
```
步骤 1:搜索 WASM 加载代码
[js-reverse] search_in_sources(query="WebAssembly|.wasm|instantiate")
步骤 2:找到 WASM 文件
[js-reverse] list_network_requests(resourceTypes=["Other"])
→ 找到 .wasm 文件的请求
步骤 3:分析 WASM 调用
[js-reverse] search_in_sources(query="exports.|instance.exports")
→ 找到导出函数的调用代码
步骤 4:追踪输入输出
[js-reverse] set_breakpoint_on_text(text="wasm导出函数调用")
触发请求 →
[js-reverse] get_paused_info → 查看入参
[js-reverse] step_over → 执行函数
[js-reverse] get_paused_info → 查看返回值
步骤 5:在浏览器中测试
[js-reverse] evaluate_script(function="调用wasm函数并返回结果")
→ 验证 I/O 关系
步骤 6:下载 WASM 文件
[chrome-devtools] get_network_request(reqid=WASM请求ID, responseFilePath="./project/main.wasm")
```
### 场景 5:WebSocket 通信分析
**目标**:分析 WebSocket 消息格式和加密
```
步骤 1:列出 WS 连接
[js-reverse] list_websocket_connections()
步骤 2:分析消息模式
[js-reverse] analyze_websocket_messages(wsid=连接ID, direction="sent")
[js-reverse] analyze_websocket_messages(wsid=连接ID, direction="received")
步骤 3:获取具体消息
[js-reverse] get_websocket_messages(wsid=连接ID, show_content=true)
步骤 4:搜索 WS 相关代码
[js-reverse] search_in_sources(query="WebSocket|ws.send|onmessage")
```
## 高级技巧
### 使用 trace_function 自动记录函数调用
```
[js-reverse] trace_function(
functionName="encrypt",
logArgs=true,
logThis=false,
pause=false
)
```
→ 每次 `encrypt` 被调用时自动记录参数,不暂停执行
### 使用条件断点
```
[js-reverse] set_breakpoint_on_text(
text="fetch(",
condition="arguments[0].indexOf('/api/data') !== -1"
)
```
→ 只在请求特定接口时暂停
### 使用 inject_before_load 进行预分析
```
[js-reverse] inject_before_load(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);
`)
```
### 使用 evaluate_script 提取运行时数据
```
[js-reverse] evaluate_script(function=`
// 提取当前页面的所有 Cookie
JSON.stringify(document.cookie.split('; ').reduce((obj, pair) => {
const [k, v] = pair.split('=');
obj[k] = v;
return obj;
}, {}))
`)
```
## 两个 MCP 的分工原则
| 需求 | 使用 js-reverse | 使用 chrome-devtools |
|------|----------------|---------------------|
| 搜索 JS 源码 | ✅ `search_in_sources` | ❌ |
| 设置断点 | ✅ `set_breakpoint_on_text` | ❌ |
| 单步调试 | ✅ `step_into/over/out` | ❌ |
| 函数追踪 | ✅ `trace_function` | ❌ |
| 注入 Hook | ✅ `inject_before_load` | ❌ |
| 页面截图 | ✅ 可以 | ✅ 更灵活(指定元素) |
| UI 交互(点击/输入) | ❌ | ✅ `click/fill/type_text` |
| 模拟 UA/设备 | ❌ | ✅ `emulate` |
| DOM 快照 | ❌ | ✅ `take_snapshot` |
| 保存请求响应到文件 | ❌ | ✅ `get_network_request(responseFilePath)` |
| WebSocket 分析 | ✅ 完整支持 | ❌ |
| 请求调用栈 | ✅ `get_request_initiator` | ❌ |
| 执行 JS | ✅ 支持 `mainWorld` 选项 | ✅ 支持 `args` 传 uid |