【Web逆向】Yakit热加载之file.ReadFile+js.Run调用本地js加解密Vulinbox靶场CryptoJS.AES(CBC)

admin 2026-01-13 14:59:52 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍利用Yakit热加载实现Web逆向加解密。针对Vulinbox靶场CryptoJS.AES前端加密场景,通过编写本地JS脚本结合file.ReadFile与js.Run接口,在WebFuzzer中实时转换流量为明文,成功对加密登录表单进行字典爆破。 综合评分: 88 文章分类: 逆向分析,WEB安全,安全工具,渗透测试,实战经验


cover_image

【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)》

2026年云与威胁报告 网络安全文章

2026年云与威胁报告

文章总结: 报告指出2026年网络安全面临GenAI带来的叠加风险,SaaSgenAI使用激增导致数据违规事件翻倍,源代码和敏感数据泄露严重。影子AI及智能体A
2026年该挖什么漏洞 网络安全文章

2026年该挖什么漏洞

文章总结: 本文预测2026年漏洞挖掘应聚焦WebLLM攻击,如利用RAG和API集成导致的数据泄露及Prompt注入。凭证填充攻击日益严重,建议使用泄露凭证搜
评论:0   参与:  0