文章总结: 本文介绍利用Yakit结合JsRpc实现前端加解密自动化,免除抠代码补环境。详细阐述了配置JsRpc服务器、编写Yakit插件及浏览器注入脚本的步骤,并演示通过WebFuzzer热加载功能对加密参数进行自动化爆破,提供了实战代码示例与解决方案,提升渗透测试效率。 综合评分: 91 文章分类: 渗透测试,WEB安全,安全工具,实战经验
yakit 调用jsRpc加解密,免去抠代码补环境
原创
进击的hack
进击的HACK
2025年4月3日 07:50 江苏
声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途给予盈利等目的,否则后果自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
字数 1567,阅读大约需 8 分钟
前言
这个之前我也介绍过burpsuite的。 前端加密对抗练习靶场 encrypt-labs 正好最近在研究yakit,重新写一份用yakit的。
JsRpc
远程调用(rpc)浏览器方法,免去抠代码补环境。
项目地址
- • 项目地址:https://github.com/jxhczhl/JsRpc
基本介绍
运行服务器程序和js脚本 即可让它们通信,实现调用接口执行js获取想要的值(加解密)
原理:在网站的控制台新建一个WebScoket客户端链接到服务器通信,调用服务器的接口 服务器会发送信息给客户端 客户端接收到要执行的方法执行完js代码后把获得想要的内容发回给服务器 服务器接收到后再显示出来
说明:本方法可以https证书且支持wss
基本使用方法
releases 下载编译好的文件,我是Windows,下载amd exe的,命名为jsrpc.exe。
下载 config.yaml 放置在jsrpc.exe同目录下
- • https://github.com/jxhczhl/JsRpc/blob/main/config.yaml
BasicListen: "0.0.0.0:12080" # 不想暴露公网/局域网可改成127.0.0.1:port
HttpsServices:
IsEnable: false # 是否启用https/wss服务
HttpsListen: "0.0.0.0:12443"
PemPath: "hl98.cn.pem"
KeyPath: "hl98.cn.key"
DefaultTimeOut: 30 # 当执行端没有返回值时,等待%d秒返回超时
CloseLog: false # 关闭一些日志
CloseWebLog: false # 关闭Web服务访问的日志
Mode: release # release:发布版本 debug:调试版 test:测试版本
Cors: false # 是否开启CorsMiddleWare中间件--默认不开启
运行 jsrpc.exe
yakit插件 JsRPC解密
yakit 调用插件,有一个非常好的地方,那就是即写即用,不像burpsuite编写插件,需要额外的环境。
我们看一下JsRPC解密插件
handle = func(origin /*string*/) {
//JSrpc的group,默认的
group = "zzz";
//jsrpc的action
action = "decrypt";
rsp,rep = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group="+group+"&action="+action+"¶m="+codec.EncodeUrl(origin), false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))~
return json.loads(rsp.GetBody())["data"];
}
我们需要在意的点是
- • group jsRpc配置的组,不过zzz是默认的,可以不修改
- • action = “decrypt”; 这个需要和后续在浏览器中注入的action对应
顺带一提,上述代码在传递js时会报错,它没把json很好处理
我们重新修改一下脚本,将json转成字符串
handle = func(origin /*string*/) {
//JSrpc的group
group = "zzz";
//jsrpc的action
action = "decrypt";
if (origin[0] == "{" && origin[-1] == "}"){
rsp,rep = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group="+group+"&action="+action+"¶m="+json.dumps(origin), false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))~
return json.loads(rsp.GetBody())["data"];
} else{
rsp,rep = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group="+group+"&action="+action+"¶m="+codec.EncodeUrl(origin), false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))~
return json.loads(rsp.GetBody())["data"];
}
}
OK
插件注意这两项
案例 encrypt靶场
项目地址:https://github.com/SwagXz/encrypt-labs
docker搭建:https://github.com/Ta0ing/encrypt-labs-docker/tree/main 默认密码:admin/123456
AES 固定 key
输入账号密码,选择第一个AES 固定 key
查看请求返回包
如果账号密码正确,后端会返回true
操作步骤
注入 JsEnv_Dev.js https://github.com/jxhczhl/JsRpc/blob/main/resouces/JsEnv_Dev.js
打开JsEnv 复制粘贴到网站控制台(注意:可以在浏览器开启的时候就先注入环境,不要在调试断点时候注入)
如果浏览器出现下面的警告,手动输入 allow pasting ,不能复制
不报错,说明注入成功
下断点调试,定位加解密位置 发现
下断点调试,是不是经过这里
找到加密点,传入的参数是json转的字符串
注入环境后连接通信 注意先关闭调试,取消断点
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");
编写加密代码 分析加密函数的输入点和输出点,编写代码,在console控制台输入下面代码
function _0x2fe90c(_0x1d8ccd, _0x579d33) {
return _0x4f79d5(_0x1d8ccd - -0x6d, _0x579d33);
}
function _0x4f79d5(_0x8e93b8, _0x5e1416) {
return _0x30d2(_0x8e93b8 - 0x26, _0x5e1416);
}
function _0x30d2(_0xb85c4e, _0xd19a71) {
const _0x30d2f4 = _0xd19a();
return _0x30d2 = function(_0x37ab03, _0x251c3f) {
_0x37ab03 = _0x37ab03 - 0x156;
let _0x362566 = _0x30d2f4[_0x37ab03];
return _0x362566;
}
,
_0x30d2(_0xb85c4e, _0xd19a71);
}
function encrypts_aes(data){
const _0x67b862 = CryptoJS['enc']['Utf8']['parse']('1234567890123456')
, _0x2d9cd5 = CryptoJS['enc'][_0x2fe90c(0x118, 0x11a)]['parse']('1234567890123456')
, _0x1375d7 = CryptoJS['AES'][_0x2fe90c(0x119, 0x11c)](data, _0x67b862, {
'iv': _0x2d9cd5,
'mode': CryptoJS[_0x2fe90c(0x11a, 0x11b)]['CBC'],
'padding': CryptoJS[_0x2fe90c(0x11b, 0x11e)][_0x2fe90c(0x11c, 0x12c)]
})[_0x2fe90c(0x11d, 0x10e)]()
return _0x1375d7;
}
因为这次环境是混淆,缺少什么函数,就在console控制台输入指定函数
测试函数能否成功执行:
带参获取值
//写一个传入字符串,返回base64值的接口(调用内置函数btoa)
demo.regAction("decrypt", function (resolve,param) {
//这样添加了一个param参数,http接口带上它,这里就能获得
var base666 = encrypts_aes(param)
resolve(base666);
})
- • action的字符串”decrypt”和yakit上的对应
yakit jsRpc加密尝试 右边——》插件扩展——》jsRpc
复制右侧的字符串
后端正常返回,说明后端解密成功
yakit webfuzzer 热加载
如果只是右键加密,不符合我们的需要,我们想要在burpsuite中autodecoder插件一样的效果。 在webfuzzer中的encryptedData中输入明文,yakit自动加密,然后发送到后端
我们可以使用热加载功能 关闭禁用热加载选项(默认关闭)
本次案例,只涉及修改请求,不涉及修改响应,所以只需关注beforeRequest
// beforeRequest 允许在每次发送数据包前对请求做最后的处理,定义为 func(https bool, originReq []byte, req []byte) []byte
// https 请求是否为https请求
// originReq 原始请求
// req 请求
beforeRequest = func(https, originReq, req) {
// 我们可以将请求进行一定的修改
/*
一个替换请求参数a的例子
poc.ReplaceHTTPPacketQueryParam(req, "a", "bbb")
*/
// 将修改后的请求返回
return []byte(req)
}
我们将插件中的函数复制到热加载中,命名为jsrpcReq
jsrpcReq = func(origin /*string*/) {
//JSrpc的group
group = "zzz";
//jsrpc的action
action = "decrypt";
if (origin[0] == "{"){
rsp,rep = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group="+group+"&action="+action+"¶m="+json.dumps(origin), false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))~
return json.loads(rsp.GetBody())["data"];
} else{
rsp,rep = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group="+group+"&action="+action+"¶m="+codec.EncodeUrl(origin), false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))~
return json.loads(rsp.GetBody())["data"];
}
}
// beforeRequest 允许在每次发送数据包前对请求做最后的处理,定义为 func(https bool, originReq []byte, req []byte) []byte
// https 请求是否为https请求
// originReq 原始请求
// req 请求
beforeRequest = func(https, originReq, req) {
// 我们可以将请求进行一定的修改
postParams = poc.GetAllHTTPPacketPostParams(req /*type: []byte*/)
encryptedParam =jsrpcReq(postParams["encryptedData"])
req = poc.ReplaceHTTPPacketPostParam(req, "encryptedData", encryptedParam)
// 将修改后的请求返回
return []byte(req)
}
加密流程
- • poc.GetAllHTTPPacketPostParams 从传入的req数据包中获取所有Post参数
- • jsrpcReq 将 encryptedData 的值发送到jsRpc的API中,返回值是加密后的参数值
- • poc.ReplaceHTTPPacketPostParam 替换req中Post参数名为 encryptedData 的参数值,然后将修改后的数据包返回
保存
发送请求
在请求包中插入fuzz标签,进行密码爆破 注意设置并发线程为1
结果
预告
Yakit的web fuzzer是一个很棒的模块。
后续我会讲一下它的序列功能,它能把多个数据包组合起来,很方便的从上一个响应中拿出需要的变量,并通过热加载修改为我们想要的值,在加解密或者过校验中很有用。
提前预告一下,师傅们可以点个关注哦~
往期推荐
代码审计 | 一次JWT任意用户登录审计
Yakit JWT Token 弱口令枚举
yakit 弱口令爆破与未授权检测
yakit 验证码识别 进行webfuzzer
yakit 安装和初次使用
数据库自动取样工具DataMiner
burpsuite指纹识别插件合集
如何最大限度的利用poc发现漏洞
Slack 安全服务集成化工具平台
unidbg补环境实战
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:进击的HACK 进击的hack《yakit 调用jsRpc加解密,免去抠代码补环境》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论