论坛首页 密码学讨论区 阅读主题

[原创]【银行逆向百例】10小程序逆向之Yakit 魔术方法beforeRequest实时修改签名

160 浏览 1 回复
#1 楼主 2026-06-01 21:09:08
“ 我们在日常生活中度过的每一天,实际上也许是连续发生的奇迹也说不定呢。——《日常》E04 ”01环境版本
环境:电脑,Windows 11 专业版 23H2软件:Yakit,v1.4.2-0613微信,Windows 3.9.10.19KillWxapkg,2.4.1
02操作步骤1、响应加密,无法分析
2、请求签名,无法重放
3、开启DevToolsb95K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6m8j5$3E0A6N6r3g2K6i4K6u0r3d9$3W2D9L8q4N6^5j5i4m8C8k6H3`.`.
4、进入DevTools03签名分析
5、网络跟调用堆栈最顶层
6、依次点击调用堆栈,在Re这一步发现signStr有结果显示
7、发现请求签名参数signStr = b.header.signStr = p
8、分析签名p生成逻辑w == 1,p = (0, r.default)(M + b.header.reqFlowNo)
w == 2,p = (0, r.default)(M + b.header.busiCode)
(0,r.default)等价SHA1
04解密分析

10、搜索decrypt关键字定位到解密函数,t.body是响应的body参数
11、l = p(c, t)
12、进入p函数内部
13、e.data.header.reqClient=evcc_v2,拼接o+i返回n,也就是密钥l如果e.data.header.reqClient包含"evcc"和"v2",返回o+i,也就是r.nonce+r.reqFlowNo
如果只有"evcc",返回去掉"-"的r.reqFlowNo
如果不包含"evcc",返回空字符串""
14、抓包分析流量,当请求中的reqClient=evcc_v2,解密函数密钥l=nonce+reqFlowNo15、响应参数body赋值给t.body,nonce+reqFlowNo赋值给l,调用解密函数
04JsRpc配置
16、导出r函数globalThis.r = r;
17、注入小程序的JsRpc环境d43K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6B7P5r3S2U0P5X3S2D9i4K6u0r3d9Y4y4d9M7r3y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4u0W2M7$3!0#2j5$3g2K6i4K6u0r3g2$3g2o6K9r3q4@1i4K6g2X3c8r3g2$3i4K6u0W2K9Y4x3`.
18、连接通信var demo = new Hlclient("ws://192.168.14.159:12080/ws?group=zzz");
19、注册解密函数,这里需要传入密钥和密文两个值demo.regAction("decrypt", function (resolve, param) {
    console.log("[decrypt] 接收到参数:", JSON.stringify(param));
    var key = param["key"];
    var body = param["body"];
    var data = r.decryptAES(body, key);
    resolve(data);
});
20、构造param,这里需要注意密文过长浏览器无法处理,使用python测试import requests
import json

payload = {
    "key": "xxx",
    "body": "xxx"
url = "e1aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0p5@1i4K6u0W2x3e0f1&6i4K6y4m8x3e0t1H3z5o6m8Q4x3V1k6Y4L8#2)9K6c8X3N6J5L8%4g2H3i4K6y4p5P5Y4A6*7i4K6t1$3j5h3#2H3i4K6y4n7j5h3y4@1K9h3!0F1i4K6y4p5k6r3g2U0M7Y4W2H3N6q4)9J5y4Y4q4#2L8%4c8Q4x3@1t1`.

print(response.text)
05Yakit热加载
21、提取响应参数nonce+reqFlowNo当作密钥和密文body一起传入param,热加载实现实时明文hijackSaveHTTPFlow = func(flow /* *yakit.HTTPFlow */, modify /* func(modified *yakit.HTTPFlow) */, drop/* func() */) {
    req = str.Unquote(flow.Request)~
    rsp = str.Unquote(flow.Response)~

    // ================================
    // 解密响应中的 body 字段
    // ================================
    if str.Contains(rsp, "\"body\":\"") {
        // 提取响应中的 JSON 数据
        rspLines := str.Split(rsp, "\r\n")
        var jsonBody

        for i, line := range rspLines {
            if line == "" && i+1 < len(rspLines) {
                jsonBody = rspLines[i+1]
                break

        if jsonBody != "" {
            // 提取 nonce
            nonceParts := str.Split(jsonBody, "\"nonce\":\"")
            var nonce
            if len(nonceParts) >= 2 {
                nonceEnd := str.Split(nonceParts[1], "\"")[0]
                nonce = nonceEnd

            // 提取 reqFlowNo


...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-287341.htm
#2 2026-06-01 21:09:08
写的很详细呀!

请登录后参与讨论

立即登录 注册账号