【古法渗透】jsrpcmitmproxy联动burp实现加密自动化"

admin 2026-10-18 06:56:47 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

【古法渗透】 jsrpc mitmproxy联动burp实现加密自动化

原创

暗月大徒弟
暗月大徒弟

moonsec

2026年8月4日 12:12
广东

在小说阅读器读本章

去阅读

免责声明:本公众号所提供的文字和信息仅供学习和研究使用,不得用于任何非法用途。我们强烈谴责任何非法活动,并严格遵守法律法规。读者应该自觉遵守法律法规,不得利用本公众号所提供的信息从事任何违法活动。本公众号不对读者的任何违法行为承担任何责任。

一、介绍

JsRpc 是黑脸怪开源、Go 后端 + 前端 JS 注入、基于 WebSocket 双向长连接 的 RPC 远程调用工具,核心定位:JS 逆向免补环境神器,项目地址:https://github.com/weixinpad/JsRpc

二、运行原理

浏览器页面注入一段 JsRpc 环境 JS,主动通过 WebSocket 连接本地 Go 服务端;你在 Python/HTTP 接口下发指令,让目标网页原生浏览器环境执行 JS 代码 / 加密函数,结果回传给本地,彻底不用在 Node.js 里模拟 DOM、BOM、浏览器内置 API 补环境。

三、整体结构

  1. Server 服务端:Go 语言编写,监听 HTTP + WebSocket,默认端口 12080
  2. Browser 客户端:浏览器页面注入 JsEnv\_De.js 脚本(JS 客户端)
  3. Caller 调用端:Python /curl/ Burp / 自己写的程序,通过 HTTP 发指令

核心通信链路:调用端 → HTTP → Go 服务 → WebSocket 长连接 → 浏览器执行 JS → 原路返回结果

四、jsrpc实战操作

下载js前端加密对抗练习靶场  https://github.com/SwagXz/encrypt-labs 在本地进行搭建

使用phpstudy 搭建 网站 修改database.php数据库配置信息 导入sql导入数据库 访问即可

账号和密码 admin/123456

加密分析

登录之后 选择 aes固定key

查看网络发现是一段密文

js分析

搜寻关键词  encrypt  查看代码 js代码都是经混饶 断点调试

查看整个加密方式  使用CryptoJS库对进行aes进行加密 固定的iv和key都是 1234567890123456

 const _0x67b862 = CryptoJS['enc']['Utf8']['parse']('1234567890123456')
      , _0x2d9cd5 = CryptoJS['enc'][_0x2fe90c(0x118, 0x11a)]['parse']('1234567890123456')
      , _0x1375d7 = CryptoJS['AES'][_0x2fe90c(0x119, 0x11c)](_0x807d91, _0x67b862, {
        'iv': _0x2d9cd5,
        'mode': CryptoJS[_0x2fe90c(0x11a, 0x11b)]['CBC'],
        'padding': CryptoJS[_0x2fe90c(0x11b, 0x11e)][_0x2fe90c(0x11c, 0x12c)]
    })[_0x2fe90c(0x11d, 0x10e)]()
      , _0x550d63 = 'encryptedData=' + encodeURIComponent(_0x1375d7);

主要的作用对传入的字符串字符串进行aes加密接着url编码返回赋值

这是没有经过混饶的代码

function encryptData(data) {
  const key = CryptoJS.enc.Utf8.parse('1234567890123456');
  const iv = CryptoJS.enc.Utf8.parse('1234567890123456');
  return CryptoJS.AES.encrypt(data, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  }).toString();
}

使用jsrcp调用该混饶代码

在jsrcp目录中运行该window\_amd64.exe服务器端

在目录中 resouces\JsEnv\_Dev.js 赋值该代码到js终端中执行

var rpc_client_id, HlClient = function (wsURL) {
  this.wsURL = wsURL;
  this.handlers = {
    _execjs: function (resolve, param) {
      try {
        var fn = new Function('return (async () => { return (' + param + ') })()');
        var result = fn();
        if (result && typeof result.then === 'function') {
          result.then(function(res) {
            resolve(res !== undefined ? res : \"执行成功(无返回值)\");
          }).catch(function(err) {
            resolve(\"执行错误: \" + (err.message || err));
          });
        } else {
          resolve(result !== undefined ? result : \"执行成功(无返回值)\");
        }
      } catch (err) {
        resolve(\"语法错误: \" + (err.message || err));
      }
    }
  };
  this.socket = undefined;
  if (!wsURL) {
    throw new Error('wsURL can not be empty!!')
  }
  this.connect()
}
HlClient.prototype.connect = function () {
  if (this.wsURL.indexOf(\"clientId=\") === -1 && rpc_client_id) {
    this.wsURL += \"&clientId=\" + rpc_client_id
  }
  console.log('begin of connect to wsURL: ' + this.wsURL);
  var _this = this;
  try {
    this.socket = new WebSocket(this.wsURL);
    this.socket.onmessage = function (e) {
      _this.handlerRequest(e.data)
    }
  } catch (e) {
    console.log(\"connection failed,reconnect after 10s\");
    setTimeout(function () {
      _this.connect()
    }, 10000)
  }
  this.socket.onclose = function () {
    console.log('rpc已关闭');
    setTimeout(function () {
      _this.connect()
    }, 10000)
  }
  this.socket.addEventListener('open', (event) => {
    console.log(\"rpc连接成功\");
    this._reportActions();
  });
  this.socket.addEventListener('error', (event) => {
    console.error('rpc连接出错,请检查是否打开服务端:', event.error);
  })
};
HlClient.prototype.send = function (msg) {
  this.socket.send(msg)
}
HlClient.prototype.regAction = function (func_name, func) {
  if (typeof func_name !== 'string') {
    throw new Error(\"an func_name must be string\");
  }
  if (typeof func !== 'function') {
    throw new Error(\"must be function\");
  }
  console.log(\"register func_name: \" + func_name);
  this.handlers[func_name] = func;
  this._reportActions();
  return true
}
HlClient.prototype._reportActions = function () {
  var actions = Object.keys(this.handlers);
  if (this.socket && this.socket.readyState === WebSocket.OPEN) {
    this.send(JSON.stringify({
      \"action\": \"_registerActions\",
      \"message_id\": \"\",
      \"response_data\": JSON.stringify(actions)
    }));
  }
}
HlClient.prototype.handlerRequest = function (requestJson) {
  var _this = this;
  try {
    var result = JSON.parse(requestJson)
  } catch (error) {
    console.log(\"请求信息解析错误\", requestJson);
    return
  }
  if (result[\"registerId\"]) {
        rpc_client_id = result['registerId']
        return
    }
    if (!result['action'] || !result[\"message_id\"]) {
        console.warn('没有方法或者消息id,不处理');
        return
    }
    var action = result[\"action\"], message_id = result[\"message_id\"]
    var theHandler = this.handlers[action];
    if (!theHandler) {
        this.sendResult(action, message_id, 'action没找到');
        return
    }
    try {
        if (!result[\"param\"]) {
            const async_result = theHandler(function (response) {
                _this.sendResult(action, message_id, response);
            })
            if (async_result && typeof async_result.then === \"function\") {
                async_result.catch(e => {
                    _this.sendResult(action, message_id, \"\" + e);
                });
            }
            return
        }
        var param = result[\"param\"]
        try {
            param = JSON.parse(param)
        } catch (e) {
        }
        theHandler(function (response) {
            _this.sendResult(action, message_id, response);
        }, param)
    } catch (e) {
        console.log(\"error: \" + e);
        _this.sendResult(action, message_id, \"\" + e);
    }
}
HlClient.prototype.sendResult = function (action, message_id, e) {
    if (typeof e === 'object' && e !== null) {
        try {
            e = JSON.stringify(e)
        } catch (v) {
            console.log(v)
        }
    }
    this.send(JSON.stringify({\"action\": action, \"message_id\": message_id, \"response_data\": e}));
}

如图

注入环境之后连接通信 grup是组 一般不用设置使用默认的就可以了

var demo = new HlClient(\"ws://127.0.0.1:12080/ws?group=zzz\");

在服务端上回显信息表示连接成功。

动态注册函数

在js中选择替换修改js内容  选择文件夹

修改后文件进行保存 ctrl+f5进行刷新

 const _0x67b862 = CryptoJS['enc']['Utf8']['parse']('1234567890123456')
    const _0x2d9cd5 = CryptoJS['enc'][_0x2fe90c(0x118, 0x11a)]['parse']('1234567890123456')

    demo.regAction(\"encryptest\", function (resolve,param) {
          const  _0x807d91 = JSON['stringify'](param);
          const  _0x1375d7 = CryptoJS['AES'][_0x2fe90c(0x119, 0x11c)](_0x807d91, _0x67b862, {
            'iv': _0x2d9cd5,
            'mode': CryptoJS[_0x2fe90c(0x11a, 0x11b)]['CBC'],
            'padding': CryptoJS[_0x2fe90c(0x11b, 0x11e)][_0x2fe90c(0x11c, 0x12c)]
        })[_0x2fe90c(0x11d, 0x10e)]()
        const _0x550d63 = 'encryptedData=' + encodeURIComponent(_0x1375d7);
        resolve(_0x550d63);
    });

encryptest 是注册的函数名  resolve是返回的内容  param是传入的参数

再进行调用

http://127.0.0.1:12080/go?group=zzz&action=encryptest&param={\"username\":\"admin\",\"password\":\"123456\"}

python编写调用脚本

encrypt\_demo.py

import json
import requests

def encrypt(data):
    url = \"http://127.0.0.1:12080/go\"
    params = {
        \"group\": \"zzz\",
        \"action\": \"encryptest\",
        \"param\": data
    }
    response = requests.get(url, params=params)
    context = response.json()['data']
    return context

data={\"username\":\"admin\",\"password\":\"123456\"}
body_data = json.dumps(data)

print(encrypt(body_data))

执行返回 返回加密的字符串

五、mitmproxy联动 burp调用jsrpc

mitmproxy 是一个“中间人代理”。它位于你的客户端(如浏览器、手机应用程序)和目标服务器之间,拦截、检查、和重放所有流经的 HTTP/HTTPS 请求和响应。

将mitmproxy作为burp的上游代理,当请求包经过mitmproxy时,通过python脚本处理请求体(&searchCond之前的部分)后传给jsrpc进行加密,mitmproxy将请求体中的sign替换后发送给服务端,流程图如下。

安装

pip install  mitmproxy

mitmproxy 是可以加载python脚本处理数据包

import json
from urllib.parse import parse_qs
from mitmproxy import http
import requests

def encrypt(data):
    url = \"http://127.0.0.1:12080/go\"
    params = {
        \"group\": \"zzz\",
        \"action\": \"encryptest\",
        \"param\": data
    }
    response = requests.get(url, params=params)
    context = response.json()['data']
    return context

class Demo:

    def request(self, flow: http.HTTPFlow) -> None:
        url = \"/encrypt/aes.php\"
        if flow.request.method == \"POST\" and flow.request.path == url:
            if \"encryptedData\" in flow.request.text:
                # 解析POST表单请求体,转成字典
                data = parse_qs(flow.request.text)
                encrypt_data = data.get(\"encryptedData\", [''])[0]
                new_data = encrypt(encrypt_data)
                flow.request.text = new_data

addons = [Demo()]

使用命令

mitmproxy -p 端口 -s 指定脚本

执行命令

mitmproxy -p 8899 -s C:\\Users\\moon\\PycharmProjects\\PythonProject\\encrypt_burp.py

运行没有出错 在burp中设置上游代理

接着提交数据包 返回true

接着可以测试穷举

参考  https://www.cnblogs.com/xiaoqiuni/p/18860405

需要本文相关工具

关注公众号回复【20260804】


【古法渗透】jsrpcmitmproxy联动burp实现加密自动化" 网络安全文章

【古法渗透】jsrpcmitmproxy联动burp实现加密自动化"

本文介绍JsRpc工具与mitmproxy、Burp联动实现加密自动化渗透测试。JsRpc基于WebSocket实现浏览器与本地Go服务端通信,通过注入JS脚本调用浏览器原生环境执行加密函数,避免Node.js补环境。实战演示了在加密靶场中分析AES加密、注入JsRpc环境并动态注册函数,最终实现自动化调用加密函数。该方法可简化JS逆向中的加密处理流程,提升渗透测试效率。
安全快报|英国警察国家法律数据库遭非法访问导致警方和政府人员身份信息泄露" 网络安全文章

安全快报|英国警察国家法律数据库遭非法访问导致警方和政府人员身份信息泄露"

本周安全快报汇总了八起重大数据泄露事件,包括英国警察数据库遭非法访问、中亚政府机构被后门攻击、瑞士政府IT系统遭SharePoint漏洞入侵、美国金融机构和供水系统遭勒索软件攻击、生物制药巨头安进公司及医疗科技公司CareCloud数据泄露、以及DentaQuest超1500万用户数据被窃。攻击手法多样,涉及配置不当的云服务、未修复漏洞及协同攻击,影响范围广泛。建议组织加强云服务配置管理、及时修补漏洞并完善应急响应机制。
评论:0   参与:  0