跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScriptAI大前端算法

AI 赋能 JS 逆向:MCP+Skill+autoDecoder 自动化加密分析方案

一种结合 AI 技术的 JS 逆向自动化方案。通过 chrome-devtools-mcp 连接浏览器,利用 Skill 规范 AI 操作,生成 JSRPC 注入代码与 Flask 代理服务,配合 Burp autoDecoder 实现参数加密的自动化处理。方案涵盖工具链介绍、配置流程及实战测试,旨在提升 JS 逆向效率,减少人工对抗成本。

心动瞬间发布于 2026/4/6更新于 2026/9/7101 浏览
AI 赋能 JS 逆向:MCP+Skill+autoDecoder 自动化加密分析方案

0x01 前言

随着前端防护手段日益复杂,参数加密场景广泛且生成逻辑经过多层混淆与封装,人工逆向方法耗时费力且高度依赖经验。本文旨在结合 chrome-devtools-mcp 的能力与 Skill 规范,实现基于 JSRPC、Flask 和 autoDecoder 的前端 JS 逆向自动化分析方案,提升逆向效率。

本文内容仅供技术学习与交流使用,请遵守相关法律法规,因违规使用产生的一切后果由使用者自行承担。

0x02 漏洞详情

传统 JS 逆向方法回顾

传统 JS 逆向工程实践中已形成一系列技术路径,主要归纳为四类:

  1. 直接修改变量法:进入调试模式,在参数加密前直接在作用域中修改参数。
  2. 中间劫持法(JS-forward):通过 JS-forward 实现在明文点处插入代码,将请求内容发送给 Burp Suite 拦截并修改后返回。
  3. 远程调用法(JS-RPC):注入到浏览器页面中的客户端,通过 WebSocket 与本地 Python 服务端相连,直接调用浏览器上下文中预先注册的 JavaScript 函数。
  4. 硬核对抗法(JS 原生):通过反混淆分析代码逻辑研究参数作用添加补环境,最终通过本地运行 JS 来加解密。

在接下来的方案中,选择远程调用法(JS-RPC)作为 MCP 赋能 JS 逆向的底座。它能将浏览器环境直接转化为加密服务接口,避免纯手动逆向的低效,又绕开了纯 JS 还原的高复杂度,适配复杂场景下的 JS 逆向对抗。

MCP 赋能的集成方案

工具链介绍

  • JSRPC:注入到浏览器页面中的客户端,建立通过 WebSocket 协议的远程过程调用机制,直接调用在浏览器上下文中预先注册好的 JavaScript 函数。
  • Flask:接收来自自动化工具如 Burp Suite 插件的请求,提取出需要加密的参数,然后通过 JSRPC 调用浏览器中的函数进行加密,最后重构请求并转发至目标服务器。
  • autoDecoder:Burp Suite 的插件,用于自动化处理应用中的加密/编码接口,自动将明文参数发送至该服务器,并完成加密请求的构建。
  • chrome-devtools-mcp:通过 Chrome DevTools Protocol 与浏览器实例建立连接,将浏览器的底层控制能力封装成一系列标准化的工具,并通过 MCP 协议暴露给 AI 客户端。

流程设计

针对远程调用法初始配置阶段中定位加密函数、编写注册代码等繁琐操作,引入 AI 技术进行赋能,让 AI 自动完成函数发现与注册代码生成,最终实现从'半自动'到'高自动'的跨越。

MCP 配置

  1. 使用 codex 来调用 MCP 服务,首先将 MCP 服务器写进 Codex 的配置。
codex mcp add chrome-devtools npx -y chrome-devtools-mcp@latest
  1. 修改 Codex 的配置文件(MAC 在 ~/.codex/config.toml),添加如下字段。
[mcp_servers.chrome-devtools]
  1. 检测是否生效。

  2. 启动 MCP 服务,当看到打开浏览器后 MCP 服务就配置好了。

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

Skill 配置

Skill 是能否一次性完成 JS 分析和代码生成的关键,创建 3 个 markdown 文件用于规范 AI 的操作以及输出。

1、主技能模板 (js-reverse-automation)

负责整体流程控制和协调,规范 AI 通过 MCP 协议连接和控制浏览器环境。

- name: js-reverse-automation description: 通过 MCP 连接浏览器,为目标自动化搭建 JS 环境,定位签名/加密函数入口,生成 JSRPC 代码,创建 Flask 代理,并输出 Burp autoDecoder 配置。
...

2、JSRPC 注入模板 (jsrpc-injection-template)

提供通用的函数拦截和远程调用能力,确保代码注入的稳定性和安全性。

// 1) 建立 JSRPC 连接
var client = new Hlclient("ws://127.0.0.1:12080/ws?group=fausto&name=burp");
// 2) 配置区
var JSRPC_CONFIG = {
    actionName: "generate_sign",
    entry: { type: "global", path: "signFunction" },
    bindThis: null,
    async: false,
    normalizeInput: function(param) { return param; },
    normalizeOutput: function(result) { return result; },
    onError: function(err) { return "ERROR_" + Date.now(); }
};
...

3、Flask 代理模板 (flask-jsrpc-proxy-template)

面向 Burp autoDecoder 的 Flask 代理服务模板,用于将请求体交给 JSRPC 生成加密后的结果并回填。

from flask import Flask, request
import requests
import json
import logging
logging.basicConfig(level=logging.DEBUG)
app = Flask(__name__)
JSRPC_URL = "http://127.0.0.1:12080/go"
JSRPC_GROUP = "fausto"
JSRPC_ACTION = "generate_sign"
SIGN_FIELD = "sign"
TIMEOUT = 5
@app.route('/encode', methods=['POST'])
def handle_encode():
    app.logger.info("- 收到来自 Burp/autoDecoder 的编码请求 -")
    data_body = request.form.get('dataBody', '')
    data_headers = request.form.get('dataHeaders', '')
    if not data_body:
        app.logger.error("未接收到 dataBody")
        return data_headers + "\r\n\r\n\r\n\r\n" + data_body if data_headers else data_body
    try:
        json_data = json.loads(data_body)
    except json.JSONDecodeError as e:
        app.logger.error(f"解析 JSON 失败:{e}")
        return data_headers + "\r\n\r\n\r\n\r\n" + data_body if data_headers else data_body
    old_sign = json_data.pop(SIGN_FIELD, None)
    app.logger.info(f"已移除旧签名:{old_sign}")
    params_for_jsrpc = {
        "group": JSRPC_GROUP,
        "action": JSRPC_ACTION,
        "param": json.dumps(json_data, ensure_ascii=False, separators=(',', ':'))
    }
    try:
        jsrpc_response = requests.get(JSRPC_URL, params=params_for_jsrpc, timeout=TIMEOUT)
        jsrpc_response.raise_for_status()
        result = jsrpc_response.json()
        new_sign = result.get('data', '')
    except requests.exceptions.RequestException as e:
        app.logger.error(f"调用 JSRPC 失败:{e}")
        new_sign = ""
    except json.JSONDecodeError as e:
        app.logger.error(f"解析 JSRPC 返回失败:{e}")
        new_sign = ""
    json_data[SIGN_FIELD] = new_sign
    new_data_body = json.dumps(json_data, ensure_ascii=False, separators=(',', ':'))
    if data_headers:
        new_content_length = len(new_data_body)
        new_headers = data_headers.replace(
            f"Content-Length: {len(data_body)}",
            f"Content-Length: {new_content_length}"
        )
        return new_headers + "\r\n\r\n\r\n\r\n" + new_data_body
    return new_data_body
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888, debug=True)

实战测试

以某大学人事管理系统为例,其 password 字段被加密,全程使用 AI 进行分析,并全程使用 AI 生成的代码进行测试。

  1. 输入触发 Skill 的提示词,AI 会提示我们需要输入的内容。
按 skill.md 的流程执行
  1. 在网页中提取我们所需的参数。

  2. 然后输入提示我们需要输入的所需参数至 codex。

目标址(URL):https://xxx/login/index
  1. 等待代码执行完成发现所需的代码均已创建完成。
Using skill js-reverse-automation (and its JSRPC/Flask/Burp templates) because the task matches the skill description.
  1. 启动 JSRPC。

  2. 在浏览器开发者工具的 Console 中,执行 JSRpc 项目中的 JsEnv_Dev.js 文件内容。

  3. 在控制台注入 AI 生成的 jsrpc_password_md5.js。

// JSRPC injection for hr.ncu.edu.cn login password MD5
// Requires Hlclient to be available in the page context.
var client = new Hlclient("ws://127.0.0.1:12080/ws?group=fausto&name=burp");
var JSRPC_CONFIG = {
    actionName: "generate_password_md5",
    entry: {
        type: "resolver",
        resolver: function () {
            if (window.$ && typeof $.md5 === "function") return $.md5;
            if (window.jQuery && typeof jQuery.md5 === "function") return jQuery.md5;
            return null;
        },
    },
    bindThis: null,
    async: false,
    normalizeInput: function (param) {
        if (param && typeof param === "object") {
            if (param.password != null) return String(param.password);
            if (param.pwd != null) return String(param.pwd);
        }
        return String(param == null ? "" : param);
    },
    normalizeOutput: function (result) {
        return result;
    },
    onError: function (err) {
        return "ERROR_" + Date.now();
    },
};
function resolveEntry(config) {
    if (config.entry.type === "resolver" && typeof config.entry.resolver === "function") {
        return config.entry.resolver();
    }
    return null;
}
client.regAction(JSRPC_CONFIG.actionName, function (resolve, param) {
    try {
        var fn = resolveEntry(JSRPC_CONFIG);
        if (typeof fn !== "function") throw new Error("md5 function not found");
        var input = JSRPC_CONFIG.normalizeInput(param);
        var ctx = JSRPC_CONFIG.bindThis || null;
        var result = fn.call(ctx, input);
        if (JSRPC_CONFIG.async && result && typeof result.then === "function") {
            result.then(function (res) {
                resolve(JSRPC_CONFIG.normalizeOutput(res));
            }).catch(function (err) {
                resolve(JSRPC_CONFIG.onError(err));
            });
            return;
        }
        resolve(JSRPC_CONFIG.normalizeOutput(result));
    } catch (error) {
        resolve(JSRPC_CONFIG.onError(error));
    }
});
  1. 测试 JSRPC 调用函数是否正常。
http://127.0.0.1:12080/go?group=fausto&action=generate_password_md5&param=111111
  1. 运行 flask_proxy_password.py。
from flask import Flask, request
import requests
import json
import logging
from urllib.parse import parse_qs, urlencode
import re
logging.basicConfig(level=logging.DEBUG)
app = Flask(__name__)
JSRPC_URL = "http://127.0.0.1:12080/go"
JSRPC_GROUP = "fausto"
JSRPC_ACTION = "generate_password_md5"
PASSWORD_FIELD = "password"
TIMEOUT = 5
CONTENT_LENGTH_RE = re.compile(r"Content-Length:\s*\d+", re.IGNORECASE)
def call_jsrpc(raw_password: str) -> str:
    params_for_jsrpc = {
        "group": JSRPC_GROUP,
        "action": JSRPC_ACTION,
        "param": raw_password,
    }
    try:
        jsrpc_response = requests.get(JSRPC_URL, params=params_for_jsrpc, timeout=TIMEOUT)
        jsrpc_response.raise_for_status()
        result = jsrpc_response.json()
        return result.get("data", "")
    except requests.exceptions.RequestException as e:
        app.logger.error(f"JSRPC request failed: {e}")
        return ""
    except json.JSONDecodeError as e:
        app.logger.error(f"JSRPC response parse failed: {e}")
        return ""
@app.route('/encode', methods=['POST'])
def handle_encode():
    app.logger.info("- incoming autoDecoder request -")
    data_body = request.form.get('dataBody', '')
    data_headers = request.form.get('dataHeaders', '')
    if not data_body:
        app.logger.error("missing dataBody")
        return data_headers + "\r\n\r\n\r\n\r\n" + data_body if data_headers else data_body
    # Try JSON first
    new_body = None
    try:
        json_data = json.loads(data_body)
        raw_pwd = str(json_data.get(PASSWORD_FIELD, ""))
        if raw_pwd:
            json_data[PASSWORD_FIELD] = call_jsrpc(raw_pwd)
        new_body = json.dumps(json_data, ensure_ascii=False, separators=(',', ':'))
    except json.JSONDecodeError:
        # Fallback to x-www-form-urlencoded
        form = parse_qs(data_body, keep_blank_values=True)
        raw_pwd = form.get(PASSWORD_FIELD, [""])[0]
        if raw_pwd:
            form[PASSWORD_FIELD] = [call_jsrpc(raw_pwd)]
        new_body = urlencode(form, doseq=True)
    if data_headers:
        new_len = len(new_body)
        new_headers = CONTENT_LENGTH_RE.sub(f"Content-Length: {new_len}", data_headers)
        return new_headers + "\r\n\r\n\r\n\r\n" + new_body
    return new_body
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888, debug=True)
  1. 测试 Flask 是否可以正常加密。
curl -X POST http://127.0.0.1:8888/encode
  1. 最后参考 Burp autoDecoder 配置说明配置 Burp 的 autoDecoder 插件,也成功加密了参数,整体完美运行下来了!

0x03 总结

本文成功实现了全自动化的 JS 分析和代码生成。对于复杂场景的 JS 代码分析可能仍需一定调试,但 AI 的优势在于可以反复迭代优化。期待更多思路交流和代码优化,共同提升安全测试能力。

目录

  1. 0x01 前言
  2. 0x02 漏洞详情
  3. 传统 JS 逆向方法回顾
  4. MCP 赋能的集成方案
  5. 工具链介绍
  6. 流程设计
  7. MCP 配置
  8. Skill 配置
  9. 实战测试
  10. 0x03 总结

更多推荐文章

查看全部
  • HTTPDNS 原理与落地实践
  • IntelliJ IDEA 2025 中 Git Local Changes 面板消失问题修复
  • Ubuntu 系统安装 Docker 及配置国内镜像源
  • 一次GitHub学生认证的记录与避坑
  • Spring Boot 数据导入导出与报表生成
  • WebODM 开源无人机地图制作完全指南
  • FLUX.1-dev WebUI 实战:实时进度监控与 24G 显存优化指南
  • 全国计算机等级考试二级 Python 历年真题及参考答案(综合应用题)
  • 2 个原因解答:为什么网络安全缺口大,招聘却很少?
  • MIT 电机模式控制:参数、场景与调试指南
  • 在 CentOS 上安装 Python 3.12
  • 中国信通院《2024年人工智能发展报告》核心观点解读
  • 使用 json-repair 库修复大模型返回的异常 JSON 格式
  • 2025 年 12 月 GitHub 十大热门开源项目
  • 主流 AI 编程模型对比与选型实战指南
  • HarmonyOS 6.0 Network Kit 深度解析:TLS 国密证书支持
  • C++ 高性能定长内存池实现原理与测试
  • 豆包 Seedream 4.0 多图融合能力测评:田园犬与三花猫多场景生成
  • OpenVLA 在机器人平台上的微调与部署指南
  • Ubuntu 24.04.2 LTS 桌面版安装、分区与配置指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online