JS逆向-安全辅助项目&Yakit热加载&魔术方法&模版插件语法&JSRpc进阶调用&接口联动
#Yakit的热加载
参考:https://yaklang.com/products/Web%20Fuzzer/fuzz-hotpatch
简单来说主要以数据包发包前和发包后的数据修改功能
1、热加载的模版内容
格式:{{yak(函数名|参数名)}}
如密码:{{yak(upper|{{x(pass_top25)}})}}
2、热加载的代码逻辑
函数名 = func(参数名) {
return 参数名
}
upper = func(s) {
// 传入的参数,类型为字符串,返回值可以是字符串或数组
return s.Upper()
}
3、热加载中的魔术方法
// beforeRequest 允许发送数据包前再做一次处理,定义为 func(origin []byte) []byte
beforeRequest = func(req) {
return []byte(req)
}
// afterRequest 允许对每一个请求的响应做处理,定义为 func(origin []byte) []byte
afterRequest = func(rsp) {
return []byte(rsp)
}
#案例1:前端验证签名(HMAC-SHA256)
热加载:
{{yak(signRequest|admin|{{x(pass_top25)}})}}
func sign(user, pass) {
return codec.EncodeToHex(codec.HmacSha256("1234123412341234", f`username=${user}&password=${pass}`)~)
}
signRequest = result => {
pairs := result.SplitN("|", 2)
dump(pairs)
return sign(pairs[0], pairs[1])
}
设置变量:
password:{{x(pass_top25)}}
{
"signature": "{{yak(signRequest|admin|{{param(password)}})}}",
"key": "31323334313233343132333431323334",
"username": "admin",
"password": "{{param(password)}}"
}
案例2:前端加密登陆(AES-CBC)
YAK Runner:
data = {
"data": "8MpsnCnixFWo67G+vrZ1Ge712JIpiDjPQvLeqNMoHdTyeMpbAdk7hnna6589oTdH",
"key": "31323334313233343132333431323334",
"iv": "bfeb9fdf041beaa31a1f136700f5e25c"
}
keyBytes = codec.DecodeHex(data.key)~
ivBytes = codec.DecodeHex(data.iv)~
a = codec.AESCBCDecryptWithPKCS7Padding(
keyBytes,
codec.DecodeBase64(data.data)~,
ivBytes
)~
println(string(a))
热加载:
{{base64({{yak(aescbc|{"username":"admin","password":"{{x(pass_top25)}}"})}})}}
aescbc = result => {
result = codec.AESCBCEncryptWithPKCS7Padding(
codec.DecodeHex(`31323334313233343132333431323334`)~,
result,
codec.DecodeHex(`bfeb9fdf041beaa31a1f136700f5e25c`)~,
)~
return string(result)
}
案例3:Yakit+JsRpc+热加载(魔术方法)
原生提交数据:{"username":"admin","password":"sssssss"}
1、上线JSRPC
执行:resouces/JsEnv_Dev.js
执行:window_amd64.exe
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");
2、执行加密代码并定义加密方法
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');
const _0x2d9cd5 = CryptoJS.enc.Utf8.parse('1234567890123456');
const _0x1375d7 = CryptoJS.AES.encrypt(data, _0x67b862, {
'iv': _0x2d9cd5,
'mode': CryptoJS.mode.CBC,
'padding': CryptoJS.pad.Pkcs7
}).toString();
return _0x1375d7;
}
3、注册JSRPC调用方法
demo.regAction("decrypt", function (resolve,param) {
//这样添加了一个param参数,http接口带上它,这里就能获得
var base666 = encrypts_aes(param)
resolve(base666);
})
4、添加JSRPC接受处理
handle=func getEnc(data){
parsedData = json.dumps(data);
rsp,rep,err = poc.Post("http://127.0.0.1:12080/go",poc.replaceBody("group=zzz&action=decrypt¶m="+parsedData, false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))
if(err){return(err)
}
return json.loads(rsp.GetBody())["data"]
}
5、添加热加载逻辑
{{yak(jsrpcReq|{{payload(pass_top25)}})}}
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的参数值,然后将修改后的数据包返回
补充异步:
https://mp.weixin.qq.com/s/amnuUWLBRg3Cqb70PLgYMQ
https://mp.weixin.qq.com/s/udTWXcmXhr3w34Xp-LEaTg
https://mp.weixin.qq.com/s/HlVc0DGjSSSdbw7z6Ae09g