JS逆向-安全辅助项目&Yakit热加载&魔术方法&模版插件语法&JSRpc进阶调用&接口联动

知识点:

JS逆向-项目-项目联动&自动接口&Yakit热加载

演示案例-JS逆向-项目-项目联动&自动接口&Yakit热加载

Yakit的热加载

参考:https://yaklang.com/products/Web Fuzzer/fuzz-hotpatch

核心比喻:给汽车换发动机,但不用停车

想象一下,你正在高速公路上开着车(这辆车就是 Yakit),你的任务是不断测试路边的各种设施(这相当于执行安全测试任务)。

突然,你觉得车的发动机(这相当于一个插件或者一段检测逻辑)不够给力,或者发现它有个小毛病,你想换一个新的。

如果没有热加载:

你得先把车完全停下来(关闭Yakit),然后熄火,打开引擎盖,把旧发动机拆下来,换上新发动机,再点火启动,重新挂挡、踩油门回到高速上。整个过程非常耗时,你的测试工作被中断了。

有了热加载:

你发现发动机需要更换。这时,你只需要在车里按一个按钮,一个新的发动机就"嗖"的一下在空中替换了旧的发动机。你的车从头到尾都没有停,一直在高速行驶,测试工作一秒都没有中断。 这个"空中换发动机"的神奇操作,就是 热加载。

总结一下,热加载是干嘛的?

热加载就是:让你在不停下Yakit主程序的情况下,立刻、马上让修改过的或新写的代码生效。


1、热加载的模版内容

bash 复制代码
格式:{{yak(函数名|参数名)}}
如密码:{{yak(upper|{{x(pass_top25)}})}}

2、热加载的代码

bash 复制代码
函数名 = func(参数名) {
    return 参数名
}

例子:
upper = func(s) {
    // 传入的参数,类型为字符串,返回值可以是字符串或数组
    return s.Upper()
}




3、热加载中的魔术方法

bash 复制代码
// 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)









bash 复制代码
热加载:

热加载的模版内容
{{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])
}


bash 复制代码
数据包设置变量:
password:{{x(pass_top25)}} //这样设置会出问题

{
  "signature": "{{yak(signRequest|admin|{{param(password)}})}}",
  "key": "31323334313233343132333431323334",
  "username": "admin",
  "password": "{{param(password)}}"
}

案例2:前端加密登陆(AES-CBC)







YAK Runner 解密调试:

bash 复制代码
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))
bash 复制代码
热加载:

热加载的模板内容
{{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+热加载(魔术方法)





1、本地上线JSRPC

浏览器控制台执行:resouces/JsEnv_Dev.js

bash 复制代码
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");

命令终端执行:window_amd64.exe

2、浏览器控制台执行加密代码并定义加密方法

bash 复制代码
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调用方法

bash 复制代码
demo.regAction("decrypt", function (resolve,param) {
    //这样添加了一个param参数,http接口带上它,这里就能获得
    var base666 = encrypts_aes(param)
    resolve(base666);
})


4、yakit添加JSRPC接受处理

bash 复制代码
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&param="+parsedData, false),poc.appendHeader("content-type", "application/x-www-form-urlencoded"))
    if(err){return(err)
    }
 
    return json.loads(rsp.GetBody())["data"]
}






5、添加热加载逻辑

bash 复制代码
模板内容:{{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 + "&param=" + 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 + "&param=" + 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的参数值,然后将修改后的数据包返回


相关推荐
用户47949283569153 小时前
用|运算符写管道?Symbol.toPrimitive让JavaScript提前用上|>语法
前端·javascript
知识分享小能手4 小时前
uni-app 入门学习教程,从入门到精通,uni-app 基础知识详解 (2)
前端·javascript·windows·学习·微信小程序·小程序·uni-app
梵得儿SHI4 小时前
Java 反射机制深度剖析:性能与安全性的那些坑
java·开发语言·安全·反射·动态代理·性能·反射机制
晴殇i5 小时前
前端鉴权新时代:告别 localStorage,拥抱更安全的 JWT 存储方案
前端·javascript·面试
来旺5 小时前
互联网大厂Java面试全解析及三轮问答专项
java·数据库·spring boot·安全·缓存·微服务·面试
码农刚子5 小时前
ASP.NET Core Blazor简介和快速入门 二(组件基础)
javascript·后端
我是日安6 小时前
从零到一打造 Vue3 响应式系统 Day 27 - toRef、toRefs、ProxyRef、unref
前端·javascript·vue.js
不如喫茶去6 小时前
VUE查询-历史记录功能
前端·javascript·vue.js
一枚前端小能手6 小时前
「周更第8期」实用JS库推荐:decimal.j
前端·javascript