一键导入
mitm-proxy
全自动分析网站加密逻辑,利用 js-reverse MCP(浏览器调试)逆向 JS 加密函数并提取密钥,生成 mitmproxy 脚本,支持三种工作模式实现 Burp Suite 与加密流量的透明交互。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
全自动分析网站加密逻辑,利用 js-reverse MCP(浏览器调试)逆向 JS 加密函数并提取密钥,生成 mitmproxy 脚本,支持三种工作模式实现 Burp Suite 与加密流量的透明交互。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | mitm_proxy |
| description | 全自动分析网站加密逻辑,利用 js-reverse MCP(浏览器调试)逆向 JS 加密函数并提取密钥,生成 mitmproxy 脚本,支持三种工作模式实现 Burp Suite 与加密流量的透明交互。 |
全自动分析网站加密逻辑,利用 js-reverse MCP(浏览器调试) 逆向 JS 加密函数并提取密钥,生成 mitmproxy 脚本,支持三种工作模式实现 Burp Suite 与加密流量的透明交互。
浏览器 → 下游mitmproxy(解密) → Burp(:8080) → 上游mitmproxy(加密) → 服务器
↑ ↓
Burp 始终看到明文 自动加解密
浏览器/source → mitmproxy(解密) → Burp(:8080)
Burp(:8080) → mitmproxy(加密) → 服务器
skill: mitm_proxy https://target.com
AI 将依次执行:
首次使用时会自动引导配置,后续跳过此步。
# 检查项目根目录是否存在 .env 配置文件
test -f .env && echo "CONFIGURED" || echo "NOT_CONFIGURED"
.env 且包含 CHROME_PATH)→ 跳过 Phase 0,直接进入 Phase 1AI 依次执行以下步骤,每步先提问 → 再验证 → 再继续:
Step 1: 询问 Chrome 路径
[配置] 检测到首次使用,需要配置 Chrome 浏览器路径。
请提供 Chrome 可执行文件的路径:
常见位置:
- Windows: C:\Program Files\Google\Chrome\Application\chrome.exe
- macOS: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
- Linux: /usr/bin/google-chrome
请输入路径(或直接回车跳过,跳过时使用默认值 "chrome"):
Step 2: AI 验证路径
# 验证 Chrome 路径是否存在(根据用户输入替换)
# AI 根据用户系统自动选择对应的验证方式:
# Windows:
if exist "USER_INPUT_PATH" (echo VALID) else (echo INVALID)
# macOS / Linux:
test -f "USER_INPUT_PATH" && echo "VALID" || echo "INVALID"
chrome)Step 3: 保存配置到 .env
# 将配置写入项目根目录的 .env 文件
echo "# AICryptoProxy 配置" > .env
echo "CHROME_PATH=USER_INPUT_PATH" >> .env
echo "" >> .env
echo "# 配置说明:" >> .env
echo "# CHROME_PATH: Chrome 可执行文件路径" >> .env
完成后提示用户:
[+] 配置已保存到 .env 文件,后续使用会自动读取。
如需修改,可编辑 .env 文件或直接删除后重新配置。
在后续步骤中,凡需要启动 Chrome 的地方,从 .env 中读取 CHROME_PATH 变量并使用:
# AI 读取配置并启动 Chrome
CHROME_PATH=$(grep CHROME_PATH .env | cut -d= -f2-)
"$CHROME_PATH" --remote-debugging-port=9222 --user-data-dir="/tmp/chrome_debug_9222" --no-first-run --no-default-browser-check --new-window "https://target.com"
从 .env 读取 CHROME_PATH 启动 Chrome(js-reverse MCP 依赖端口 9222):
# AI 从 .env 读取 CHROME_PATH 并启动
# 如果 .env 中配置了路径则使用配置的路径,否则默认用 "chrome"
CHROME_PATH=$(grep CHROME_PATH .env 2>/dev/null | cut -d= -f2-)
CHROME_PATH=${CHROME_PATH:-chrome}
"$CHROME_PATH" --remote-debugging-port=9222 --user-data-dir="/tmp/chrome_debug_9222" --no-first-run --no-default-browser-check --new-window "https://target.com" &
Windows 注意:
.env中的路径可能包含空格(如C:\Program Files\...),AI 需确保引号包裹正确。 临时目录在 Windows 下使用%TEMP%\chrome_debug_9222。
验证连接:
curl -s http://127.0.0.1:9222/json/version
# 列出页面 → 选择目标页面
# 使用 js-reverse MCP 工具:
mcp__js-reverse__list_pages
mcp__js-reverse__select_page(pageIdx=0)
使用 collect_code 自动收集页面所有 JS(包括动态加载的):
mcp__js-reverse__collect_code(
url="https://target.com",
smartMode="full",
includeInline=true,
includeExternal=true,
includeDynamic=true
)
如果文件过多,先用 summary 模式概览,再按需拉取。
在收集到的 JS 中搜索加密相关代码:
mcp__js-reverse__search_in_sources(
query="encrypt|decrypt|CryptoJS|JSEncrypt|setPublicKey|setPrivateKey",
urlFilter="target",
maxResults=50
)
mcp__js-reverse__search_in_sources(
query="AES|RSA|SM2|SM4|DES|pkcs1|pkcs7|padding|mode",
urlFilter="target",
maxResults=50
)
发现加密函数后,用 hook 记录每次调用的参数和返回值(不打断执行):
# 例: hook 全局加密函数
mcp__js-reverse__hook_function(
target="window.encryptData", # 根据实际函数名修改
logArgs=true,
logResult=true,
logStack=false
)
# 例: hook CryptoJS.AES.encrypt
mcp__js-reverse__hook_function(
target="CryptoJS.AES.encrypt",
logArgs=true,
logResult=true
)
在浏览器中执行一次目标操作(登录/查询等),触发加密函数调用:
# 用 js-reverse 在浏览器中触发操作,或者让用户手动操作
# 然后查看 hook 捕获的数据:
mcp__js-reverse__get_hook_data(hookId="CryptoJS.AES.encrypt", view="raw")
从 hook 结果中提取:
尝试使用 AI 反混淆:
mcp__js-reverse__deobfuscate_code(code="...混淆代码...", aggressive=true)
或用 browser-reverse / code-obfuscation-deobfuscation skill 辅助分析。
完成 JS 分析后,向用户展示发现的加密信息并询问模式:
[+] 加密分析完成
算法: AES-256-CBC
Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
IV: xxxxxxxxxxxxxxxxxxxxxxxx
加密字段: username, password, data
解密函数: decryptResponse(data)
请选择工作模式:
1) 双代理模式(全功能,Burp 始终明文)
2) 仅解密模式(只解密查看)
3) 仅加密模式(只加密发送,用于攻击)
根据用户选择的模式生成对应脚本。
不要猜测加密请求的格式。 在写脚本之前,先用浏览器触发一次真实请求,抓包看清请求体:
mcp__js-reverse__network_request(action="list")
mcp__js-reverse__network_request(action="get", reqid=1)
重点确认:
application/json 还是 application/x-www-form-urlencoded?常见格式对照表:
| Content-Type | 请求体示例 | 脚本处理方法 |
|---|---|---|
x-www-form-urlencoded | data=Abc...== | parse_qs 提取 → quote() 拼接回去 |
x-www-form-urlencoded | u=EncA...&p=EncB... | 每个字段独立处理 |
application/json | {"cipher":"Abc...=="} | json.loads + json.dumps |
application/json | {"data":{"user":"Enc..."}} | 深层字段替换 |
拿到真实格式后再写脚本,模板中的加解密处理部分必须按实际格式修改。
#!/usr/bin/env python3
"""
{TARGET_DOMAIN} 下游解密代理 (Browser → mitmproxy → Burp)
端口: 8082
功能: 解浏览器密文 → 明文给Burp | 加密Burp明文 → 密文回浏览器
"""
from mitmproxy import http
import json, base64, re
class DownstreamDecryptProxy:
"""下游代理: 解密浏览器请求 / 加密响应回浏览器"""
def __init__(self):
self.target_domains = ['{TARGET_DOMAIN}']
# ---- AI 提取的密钥和算法 ----
# {CRYPTO_CONFIG}
self._init_crypto()
def _init_crypto(self):
# 由 AI 根据分析结果填充
pass
def decrypt_request(self, ciphertext: str) -> str:
"""解密函数 - AI 根据 JS 逆向结果生成"""
# e.g. AES decryption
# from Crypto.Cipher import AES
# from Crypto.Util.Padding import unpad
# cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# return unpad(cipher.decrypt(base64.b64decode(ciphertext)), 16).decode('utf-8')
raise NotImplementedError()
def encrypt_response(self, plaintext: str) -> str:
"""加密函数 - AI 根据 JS 逆向结果生成"""
# 与浏览器 JS 加密方式保持一致
raise NotImplementedError()
def request(self, flow: http.HTTPFlow) -> None:
"""浏览器→Burp: 解密密文请求 → 转发明文"""
if not any(d in flow.request.pretty_url for d in self.target_domains):
return
# 检测请求体中的加密字段,解密后发给 Burp
# ... (AI 根据实际字段结构生成)
def response(self, flow: http.HTTPFlow) -> None:
"""Burp→浏览器: 加密明文响应 → 转发密文给浏览器"""
if not any(d in flow.request.pretty_url for d in self.target_domains):
return
# 检测响应体中的明文,加密后发给浏览器
# ... (AI 根据实际字段结构生成)
addons = [DownstreamDecryptProxy()]
#!/usr/bin/env python3
"""
{TARGET_DOMAIN} 上游加密代理 (Burp → mitmproxy → Server)
端口: 8083
功能: 加密Burp明文 → 密文给服务器 | 解密服务器密文 → 明文回Burp
"""
from mitmproxy import http
import json, base64, re
class UpstreamEncryptProxy:
"""上游代理: 加密Burp请求 / 解密服务器响应"""
def __init__(self):
self.target_domains = ['{TARGET_DOMAIN}']
# ---- AI 提取的密钥和算法 ----
# {CRYPTO_CONFIG}
self._init_crypto()
def _init_crypto(self):
pass
def encrypt(self, plaintext: str) -> str:
"""加密函数 - AI 生成"""
raise NotImplementedError()
def decrypt(self, ciphertext: str) -> str:
"""解密函数 - AI 生成"""
raise NotImplementedError()
def request(self, flow: http.HTTPFlow) -> None:
"""Burp→Server: 加密明文请求"""
if not any(d in flow.request.pretty_url for d in self.target_domains):
return
# 加密请求体中的明文字段
# ...
def response(self, flow: http.HTTPFlow) -> None:
"""Server→Burp: 解密密文响应"""
if not any(d in flow.request.pretty_url for d in self.target_domains):
return
# 解密响应体中的密文字段
# ...
addons = [UpstreamEncryptProxy()]
双代理启动命令:
# 终端 1: 启动上游代理 (Burp → Server, 加密),普通模式
mitmdump -s {domain}/upstream_encrypt_proxy.py -p 8083
# 终端 2: 启动下游代理 (Browser → Burp, 解密),必须用 --mode upstream 指向 Burp
mitmdump -s {domain}/downstream_decrypt_proxy.py --mode upstream:http://127.0.0.1:8080 -p 8082
# Burp Suite 配置:
# Settings → Proxy → Upstream Proxy Servers
# 规则1: *{domain}* → 127.0.0.1:8083 (上游加密)
# 浏览器代理配置:
# HTTP/HTTPS → 127.0.0.1:8082 (下游解密)
#!/usr/bin/env python3
"""
{TARGET_DOMAIN} 仅解密代理
端口: 8082
功能: 只解密响应/请求中的加密字段,Burp 看到明文
"""
from mitmproxy import http
import json, base64, re
class DecryptOnlyProxy:
def __init__(self):
self.target_domains = ['{TARGET_DOMAIN}']
# {CRYPTO_CONFIG}
self._init_crypto()
def _init_crypto(self):
pass
def decrypt(self, ciphertext: str) -> str:
"""解密函数 - AI 生成"""
raise NotImplementedError()
def response(self, flow: http.HTTPFlow) -> None:
"""仅解密服务器响应"""
if not any(d in flow.request.pretty_url for d in self.target_domains):
return
# 解密响应体中的加密字段
# ...
addons = [DecryptOnlyProxy()]
# 启动
mitmdump -s {domain}/decrypt_only_proxy.py -p 8082
# 浏览器代理 → 127.0.0.1:8082
# 或 Burp 上游代理 → 127.0.0.1:8082
#!/usr/bin/env python3
"""
{TARGET_DOMAIN} 仅加密代理
端口: 8083
功能: 加密 Burp 的明文请求后发送给服务器
"""
from mitmproxy import http
import json, base64, re
class EncryptOnlyProxy:
def __init__(self):
self.target_domains = ['{TARGET_DOMAIN}']
# {CRYPTO_CONFIG}
self._init_crypto()
def _init_crypto(self):
pass
def encrypt(self, plaintext: str) -> str:
"""加密函数 - AI 生成"""
raise NotImplementedError()
def request(self, flow: http.HTTPFlow) -> None:
"""加密 Burp 明文请求"""
if not any(d in flow.request.pretty_url for d in self.target_domains):
return
# 加密请求体中的明文字段
# ...
addons = [EncryptOnlyProxy()]
# 启动
mitmdump -s {domain}/encrypt_only_proxy.py -p 8083
# Burp → Upstream Proxy: *{domain}* → 127.0.0.1:8083
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
def aes_cbc_encrypt(plaintext: str, key: bytes, iv: bytes) -> str:
cipher = AES.new(key, AES.MODE_CBC, iv)
return base64.b64encode(cipher.encrypt(pad(plaintext.encode('utf-8'), 16))).decode()
def aes_cbc_decrypt(ciphertext: str, key: bytes, iv: bytes) -> str:
cipher = AES.new(key, AES.MODE_CBC, iv)
return unpad(cipher.decrypt(base64.b64decode(ciphertext)), 16).decode('utf-8')
def aes_ecb_encrypt(plaintext: str, key: bytes) -> str:
cipher = AES.new(key, AES.MODE_ECB)
return base64.b64encode(cipher.encrypt(pad(plaintext.encode('utf-8'), 16))).decode()
def aes_ecb_decrypt(ciphertext: str, key: bytes) -> str:
cipher = AES.new(key, AES.MODE_ECB)
return unpad(cipher.decrypt(base64.b64decode(ciphertext)), 16).decode('utf-8')
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
def rsa_encrypt(plaintext: str, public_key: str) -> str:
key = RSA.import_key(public_key)
cipher = PKCS1_v1_5.new(key)
return base64.b64encode(cipher.encrypt(plaintext.encode('utf-8'))).decode()
def rsa_decrypt(ciphertext: str, private_key: str) -> str:
key = RSA.import_key(private_key)
cipher = PKCS1_v1_5.new(key)
return cipher.decrypt(base64.b64decode(ciphertext), None).decode('utf-8')
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import base64
def sm4_encrypt(plaintext: str, key: bytes) -> str:
crypt = CryptSM4()
crypt.set_key(key, SM4_ENCRYPT)
return base64.b64encode(crypt.crypt_ecb(plaintext.encode('utf-8'))).decode()
def sm4_decrypt(ciphertext: str, key: bytes) -> str:
crypt = CryptSM4()
crypt.set_key(key, SM4_DECRYPT)
return crypt.crypt_ecb(base64.b64decode(ciphertext)).decode('utf-8')
{target_domain}/
├── ANALYSIS_REPORT.md # 详细分析报告
├── js/ # 下载的 JS 文件
├── hook_data/ # Hook 捕获的参数样本
├── downstream_decrypt_proxy.py # [模式1] 下游解密代理脚本
├── upstream_encrypt_proxy.py # [模式1] 上游加密代理脚本
├── decrypt_only_proxy.py # [模式2] 仅解密代理脚本
└── encrypt_only_proxy.py # [模式3] 仅加密代理脚本
脚本生成后,AI 必须主动 在对话中输出以下内容(不要只写在文件里,要让用户直接看到):
按模式输出对应的启动方式:
双代理模式:
# 终端 1 - 上游加密代理 (Burp → Server)
mitmdump -s {domain}/upstream_encrypt_proxy.py -p 8083
# 终端 2 - 下游解密代理 (Browser → Burp)
mitmdump -s {domain}/downstream_decrypt_proxy.py -p 8082
仅解密模式:
mitmdump -s {domain}/decrypt_only_proxy.py -p 8082
仅加密模式:
mitmdump -s {domain}/encrypt_only_proxy.py -p 8083
明确告知用户每层的代理怎么设:
Burp Suite 配置:
Settings → Proxy → Upstream Proxy Servers → 添加:
*{domain}* → 127.0.0.1:8083 (转发给上游加密代理)
浏览器代理配置:
HTTP/HTTPS → 127.0.0.1:8082 (双代理模式的下游解密代理)
或 → 127.0.0.1:8080 (其他模式,Burp 默认端口)
告诉用户如何验证加解密是否正常工作:
1. 浏览器访问 https://{domain},触发一个加密请求
2. 观察 mitmproxy 终端日志,确认输出类似:
[下游解密] POST /login
[请求解密] password: ...密文... -> 明文
3. 到 Burp 中查看,确认请求/响应已变为明文
4. 如果解密失败,检查日志中的具体错误信息
关键: 必须输出完整的启动命令和配置说明,不能只生成文件就结束。用户需要直接看到 "复制这条命令就能跑" 的信息。
admin' OR '1'='1[下游解密] POST https://api.target.com/login
[请求解密] username: ZkeeMKHSfeofC+... -> admin
[请求解密] password: eQa0WyHx5H1yO9jW... -> 123456
[+] 请求明文已转发至 Burp
[上游加密] POST https://api.target.com/login
[加密] username: admin -> ZkeeMKHSfeofC+...
[加密] password: 123456 -> eQa0WyHx5H1yO9jW...
[+] 请求密文已发送至服务器
[上游解密] GET https://api.target.com/user/info
[解密] data
[+] 响应明文已转发至 Burp
[下游加密] GET https://api.target.com/user/info
[加密] data
[+] 响应密文已返回浏览器
最容易犯的错误: 想当然地假设加密请求的格式是 data=<密文>,不验证就直接写。
正确做法:
关于 base64: 只有 x-www-form-urlencoded 且手动拼字符串时,值才需要 quote()。JSON body 不需要。
--remote-debugging-port=9222 启动curl -s http://127.0.0.1:9222/json/version~/.claude/.claude.json 中 js-reverse 配置是否正确trace_function(functionName=...) 搜索源代码中的函数search_in_sources 中搜索更精确的函数名evaluate_script 直接执行加密函数type_text 填表单 → click_element 点登录 → 弹窗出现 → click_element 点对应按钮find_clickable_elements 查看页面上所有可点击元素(包含不可见的弹窗按钮)hook_function(target="fetch") 虽然能捕获调用,但 URL、请求体等参数可能为空network_request 查看实际网络请求:
network_request(action="list") 列出请求 → 记录 reqidnetwork_request(action="get", reqid=N) 查看请求/响应详情utf-8,但网页可能用 gbk/gb2312pip install mitmproxy pycryptodome
pip install gmssl # 国密支持
pip install requests # 动态密钥获取
本 Skill 使用 js-reverse MCP 深度分析前端加密,支持三种灵活模式。输入 URL 即可从 JS 逆向到 mitmproxy 脚本全自动生成。