JsRpc联动burp实现自动加解密(详细版)

admin 2025年3月19日21:11:06评论6 views字数 4028阅读13分25秒阅读模式

免责声明:由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!

文章作者:先知社区(chenxun)

文章来源:https://xz.aliyun.com/news/17198

练手地址:https://github.com/0ctDay/encrypt-decrypt-vuls

JsRpc:https://github.com/jxhczhl/JsRpc

JsRpc基本使用

首先观察一下原始的数据包

JsRpc联动burp实现自动加解密(详细版)

可以看到除了请求体需要解密,还有请求头中的timestamp、requestId、sign 需要实时更新,所以请求包中总共有四个地方需要处理,由于是直接只用JsRpc,那么就只需要找到对应的处理位置然后调用即可,不需要弄清楚具体的处理逻辑

JsRpc联动burp实现自动加解密(详细版)
JsRpc联动burp实现自动加解密(详细版)

可以看到就是图中的几个地方处理的,具体逻辑就不分析了,主要是学会使用jsrpc

首先把这几个函数先提升到全局,需要先断点让其加载到作用域

JsRpc联动burp实现自动加解密(详细版)

然后在控制台执行下面语句提升至全局作用域

window.requestId=p//requestIdwindow.v1 = v//函数vwindow.sign=a.a.MD5//签名signwindow.l=lwindow.d=d
JsRpc联动burp实现自动加解密(详细版)

然后注入jsrpc中的js文件JsEnv_Dev.js ,注意注js的时候断点就得停止了

JsRpc联动burp实现自动加解密(详细版)

然后启动jsrpc服务端

JsRpc联动burp实现自动加解密(详细版)

再客户端连接

JsRpc联动burp实现自动加解密(详细版)

连接成功后服务端会提示新上线….然后就是将函数注册进去,即我们要怎么处理值

demo.regAction("encode",function (resolve,param) {    n=JSON.stringify(v1(param))    var request = l(n)    var time = Date.parse(new Date);    var id=requestId()    var sg = sign(n+id+time).toString()    var data={"time":"","id":"","sign":"","request":""}    data["time"]=time.toString()    data["id"]=id    data["sign"]=sg    data["request"] = request    resolve(data);})

上面是加密,下面是解密

demo.regAction("decode"function (resolve,param) {    //这样添加了一个param参数,http接口带上它,这里就能获得    var response = d(param)    resolve(response);})
JsRpc联动burp实现自动加解密(详细版)

此时就可以测试一下jsrpc处理是否能成功

JsRpc联动burp实现自动加解密(详细版)
http://127.0.0.1:12080/go?group=zzz&action=encode&param={"password":"123123","username":"asd","validCode":"ycpa"}

可以看到加密是没有任何问题的,zzz就是加入的组和你一开始连接的时候相同即可,action 即你注册的加密函数,param 就是你要处理的参数,看看解密

JsRpc联动burp实现自动加解密(详细版)

也是能够正常处理的

JsRpc联动burp

联动burp需要借助mitmproxy写脚本,或者借助其它一些burp插件也行,这里就用mitmproxy了,脚本借助gpt弄几下即可

import requestsimport jsonfrom mitmproxy import ctxdef get_rpc(param):    url = "http://127.0.0.1:12080/go"    params = {        "group""zzz",        "action""encode",        "param": param.decode('utf-8', errors='ignore')    }    try:        result = requests.get(url, params=params, timeout=5)        # ctx.log.info(f"RPC Response: {result.text}")        # 第一次解析 JSON,获取外层结构        outer_data = result.json()        # 第二次解析 data 字段(字符串 -> 字典)        inner_data = json.loads(outer_data['data'])        return inner_data  # 直接返回解析后的内层数据    except Exception as e:        ctx.log.error(f"Error in get_rpc: {str(e)}")        return Nonedef get_responseRpc(param):    url = "http://127.0.0.1:12080/go"    params = {        "group""zzz",        "action""decode",        "param": param.decode('utf-8', errors='ignore')    }    try:        result = requests.get(url, params=params, timeout=5)        outer_data = result.json()        # 第二次解析 data 字段(字符串 -> 字典)        inner_data = json.loads(outer_data['data'])        return inner_data  # 直接返回解析后的内层数据    except Exception as e:        ctx.log.error(f"Error in get_rpc: {str(e)}")        return Nonedef request(flow):    original_body = flow.request.content    ctx.log.info(f"原始请求体: {original_body}")    result = get_rpc(original_body)    if result is None:        ctx.log.error("RPC failed, skipping request modification")        return    try:        # 直接使用内层数据        flow.request.headers['timestamp'] = result['time']        flow.request.headers['requestId'] = result['id']        flow.request.headers['sign'] = result['sign']        flow.request.content = result['request'].encode('utf-8')        flow.request.headers['Content-Length'] = str(len(flow.request.content))        ctx.log.info(f"加密后的请求体: {flow.request.content}")    except Exception as e:        ctx.log.error(f"Error in request: {str(e)}")def response(flow):    response_body = flow.response.content    ctx.log.info(f"响应体: {response_body}")    result = get_responseRpc(response_body)    if result is None:        ctx.log.error("Response RPC failed, keeping original response")        return    try:        # 将解码后的字典转为 JSON 字符串并编码为字节        decoded_json = json.dumps(result, ensure_ascii=False).encode('utf-8')        flow.response.content = decoded_json        flow.response.headers['Content-Length'] = str(len(flow.response.content))        # 可选:设置 Content-Type 为 JSON        flow.response.headers['Content-Type'] = 'application/json; charset=utf-8'        ctx.log.info(f"解码后的响应体: {flow.response.content}")    except Exception as e:        ctx.log.error(f"Error in response: {str(e)}")

然后设置burp的上游代理

JsRpc联动burp实现自动加解密(详细版)

运行脚本

mitmdump -p 8081 -s .JsPython.py 
JsRpc联动burp实现自动加解密(详细版)

这样即可实现自动化加解密

当密码不正确时

JsRpc联动burp实现自动加解密(详细版)

当密码正确时,这里请求头中的三个值在burp虽然没变但实际上是已经改变了的,因为是在脚本中做的处理

JsRpc联动burp实现自动加解密(详细版)

还是非常方便滴,因为不需要去逆js了

参考

https://xz.aliyun.com/news/14689

https://xz.aliyun.com/news/12678

 

原文始发于微信公众号(七芒星实验室):JsRpc联动burp实现自动加解密(详细版)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月19日21:11:06
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JsRpc联动burp实现自动加解密(详细版)https://cn-sec.com/archives/3857870.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息