jsrpc yakit
靶机环境
https://github.com/0ctDay/encrypt-decrypt-vuls/
编译好的jar包
通过百度网盘分享的文件:前端加密env.7z
链接:https://pan.baidu.com/s/1_KK-iGgC9_Tx2MucdFlCKw?pwd=kgux
提取码:kgux
--来自百度网盘超级会员V4的分享
v_jstoos 配置
hook-console
hook-function
hook-eval
勾选 `是否在调试输出时,输出函数出发的地址`
勾选 `是否启用下面几个加解密函数挂钩输出功能`
hook-JSON.parse
hook-JSON.stringify
hook-escape
hook-atob
hook-btoa
jsrpc
项目地址
https://github.com/jxhczhl/JsRpc
操作流程注意 : 先 注入 jsrpc 在调试模式下将加密函数设为全局,非调试下向jsrcp注册action
chrome 控制台注入
function Hlclient(wsURL) {
this.wsURL = wsURL;
this.handlers = {
_execjs: function (resolve, param) {
var res = eval(param)
if (!res) {
resolve("没有返回值")
} else {
resolve(res)
}
}
};
this.socket = undefined;
if (!wsURL) {
throw new Error('wsURL can not be empty!!')
}
this.connect()
}
Hlclient.prototype.connect = function () {
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.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;
return true
}
//收到消息后这里处理,
Hlclient.prototype.handlerRequest = function (requestJson) {
var _this = this;
try {
var result = JSON.parse(requestJson)
} catch (error) {
console.log("catch error", requestJson);
result = transjson(requestJson)
}
//console.log(result)
if (!result['action']) {
this.sendResult('', 'need request param {action}');
return
}
var action = result["action"]
var theHandler = this.handlers[action];
if (!theHandler) {
this.sendResult(action, 'action not found');
return
}
try {
if (!result["param"]) {
theHandler(function (response) {
_this.sendResult(action, response);
})
return
}
var param = result["param"]
try {
param = JSON.parse(param)
} catch (e) {}
theHandler(function (response) {
_this.sendResult(action, response);
}, param)
} catch (e) {
console.log("error: " + e);
_this.sendResult(action, e);
}
}
Hlclient.prototype.sendResult = function (action, e) {
if (typeof e === 'object' && e !== null) {
try {
e = JSON.stringify(e)
} catch (v) {
console.log(v)//不是json无需操作
}
}
this.send(action + atob("aGxeX14") + e);
}
function transjson(formdata) {
var regex = /"action":(?<actionName>.*?),/g
var actionName = regex.exec(formdata).groups.actionName
stringfystring = formdata.match(/{..data..:.*..\w+..:\s...*?..}/g).pop()
stringfystring = stringfystring.replace(/\\"/g, '"')
paramstring = JSON.parse(stringfystring)
tens = `{"action":` + actionName + `,"param":{}}`
tjson = JSON.parse(tens)
tjson.param = paramstring
return tjson
}
注册到demo
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");
找到加密函数将其注册到全局
window.enc() = l
#测试
enc("123")
向jsrpc注册函数
//有参
demo.regAction("enc", function (resolve, param) {
var res = enc(String(param));
resolve(res);
})
调试
http://127.0.0.1:12080/go?group=zzz&action=enc¶m=123
断点调试全部加载
//时间戳
window.time = Date.parse
//requestId
window.id = p
//v函数
window.v1 = v
//签名
window.m = a.a.MD5
//加密
window.enc = l
注册
//md5函数
demo.regAction("req", function (resolve,param) {
//请求头
let timestamp = time(new Date());
let requestid = id();
let v_data = JSON.stringify(v1(param));
let sign = m(v_data + requestid + timestamp).toString();
//加密请求体
let encstr = enc(v_data);
let res = {
"timestamp":timestamp,
"requestid":requestid,
"encstr":encstr,
"sign":sign
};
resolve(res);
})
jsrpc 热加载配置
// 定义加密函数
func getEnc(data){
rsp,rep,err = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group=zzz&action=req¶m="+data, false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))
if(err){
return(err)
}
return json.loads(rsp.GetBody())["data"]
}
// beforeRequest 允许发送数据包前再做一次处理,定义为 func(origin []byte) []byte
beforeRequest = func(req) {
//获取请求体
req_body = poc.GetHTTPPacketBody(req)
//加密
res = getEnc(string(req_body))
//获取其他的参数
res = json.loads(res)
//修改其他的请求头
req = poc.ReplaceHTTPPacketHeader(req, "requestId", res["requestid"])
req = poc.ReplaceHTTPPacketHeader(req, "timestamp", res["timestamp"])
req = poc.ReplaceHTTPPacketHeader(req, "sign", res["sign"])
//修改请求体
req = poc.ReplaceHTTPPacketBody(req, res["encstr"])
return []byte(req)
}
// afterRequest 允许对每一个请求的响应做处理,定义为 func(origin []byte) []byte
afterRequest = func(rsp) {
return []byte(rsp)
}
// mirrorHTTPFlow 允许对每一个请求的响应做处理,定义为 func(req []byte, rsp []byte, params map[string]any) map[string]any
// 返回值回作为下一个请求的参数,或者提取的数据,如果你需要解密响应内容,在这里操作是最合适的
mirrorHTTPFlow = func(req, rsp, params) {
return params
}
解密插件
现在chrome控制台注册
//记录:这里解密函数就是d函数
window.dec = d
//向jsrpc注册
demo.regAction("decrypt", function (resolve,param) {
resolve(dec(param))
})
新建yakit插件,添加右键菜单
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"];
}
afterrequest 解密
在响应体加入 decodestr key
// 定义加密函数
func getEnc(data){
rsp,rep,err = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group=zzz&action=req¶m="+data, false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))
if(err){
return(err)
}
return json.loads(rsp.GetBody())["data"]
}
func getDec(origin){
//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"];
}
// beforeRequest 允许发送数据包前再做一次处理,定义为 func(origin []byte) []byte
beforeRequest = func(req) {
//获取请求体
req_body = poc.GetHTTPPacketBody(req)
//加密
res = getEnc(string(req_body))
//获取其他的参数
res = json.loads(res)
//修改其他的请求头
req = poc.ReplaceHTTPPacketHeader(req, "requestId", res["requestid"])
req = poc.ReplaceHTTPPacketHeader(req, "timestamp", res["timestamp"])
req = poc.ReplaceHTTPPacketHeader(req, "sign", res["sign"])
//修改请求体
req = poc.ReplaceHTTPPacketBody(req, res["encstr"])
return []byte(req)
}
// afterRequest 允许对每一个请求的响应做处理,定义为 func(origin []byte) []byte
afterRequest = func(rsp) {
// 获取响应体
rsp_body = poc.GetHTTPPacketBody(rsp)
rsp = poc.AppendHTTPPacketHeader(rsp, "decodestr", getDec(string(rsp_body)))
// 返回解码后的数据
return []byte(rsp)
}
// mirrorHTTPFlow 允许对每一个请求的响应做处理,定义为 func(req []byte, rsp []byte, params map[string]any) map[string]any
// 返回值回作为下一个请求的参数,或者提取的数据,如果你需要解密响应内容,在这里操作是最合适的
mirrorHTTPFlow = func(req, rsp, params) {
return params
}
引用文章: https://xz.aliyun.com/t/14629
yakit api: https://www.yaklang.com/docs/api/poc/
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。与我联系email c2VjaW5mby5tQGdtYWlsLmNvbQo=