开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 8212|回复: 7
收起左侧

[技术专题] 做一个网站参数加解密分析的入门流程,看求助区挺多需求

[复制链接]
发表于 2022-10-24 20:47:28 | 显示全部楼层 |阅读模式   湖北省武汉市
本帖最后由 vcdemon 于 2022-10-24 21:06 编辑

以注册接口为例:
1666596562082.png
抓包结果:
[JavaScript] 纯文本查看 复制代码
POST /TQL?Entry=PUL.register_account&RI= HTTP/1.1
Host: pul.tdx.com.cn
Connection: keep-alive
Content-Length: 148
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
sec-ch-ua-platform: "Windows"
Content-Type: text/plain
Accept: */*
Origin: https://pul.tdx.com.cn
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://pul.tdx.com.cn/site/app/pul/register.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: LST=10; ASPSessionID=12689960779600960594

[{"ATYPE":340,"AID":"@ec0:PvhToe2pW6FL0v1tQru05UKrc5uZJHC5","YZM":"1234","AUTOLOGIN":2,"APASD":"MD5@25d55ad283aa400af464c76d713c07ad","encFlg":"1"}]


返回
[JavaScript] 纯文本查看 复制代码
HTTP/1.1 200 OK
Set-Cookie: ASPSessionID=12689961020119129188;path=/;HttpOnly
Set-Cookie: LST=10;path=/
Content-Length: 77
Content-Type: application/octet-stream
Pragma: no-cache
Cache-Control: no-cache
Connection: close

[[-12543,"éªŒè¯ç ä¸æ­£ç¡®<==(S7102)PUL.register_account",0,"",0],[],[],[]]


请求参数中,AID与APASD均被加密,AID是填写的手机号,YZM是手机验证码,APASD是注册密码。
观察特点,手机号加密有前缀@ec0:,密码加密有前缀,MD5@,可以得到的结论是,至少有两种加密,密码大概率可能是md5的签名算法。

搜索字符串:ATYPE,定位到接口参数赋值的地方:
1666596700465.png
[JavaScript] 纯文本查看 复制代码
YhtRegister: function(o, i, s, r, a) {
                    var c = this
                      , u = this;
                    return new Promise(function(e, t) {
                        var n = {
                            ATYPE: 340,
                            AID: Object(m.b)(o),
                            YZM: i,
                            AUTOLOGIN: s || 1
                        };
                        r && (n.APASD = r),
                        a && (n.LABLESIGN = a),
                        n.encFlg = "1",
                        c.tdxYhtRegister([n], function(t) {
                            0 == t.ErrorCode && ("tdxios" != u.platform() && "tdxandroid" != u.platform() || 0 < Object.keys(t.tables[0][0]).length && t.tables[0][0].TDXID && (u.isNewRegister = !0),
                            e(t.Cookies))
                        })
                    }
                    )
                },

在这里,参数o是手机号明文,r是密码加密后的值。
先看手机号加密逻辑,在控制台输出加密函数Object(m.b),回车,定位到加密代码:
1666596801732.png
[JavaScript] 纯文本查看 复制代码
var o = function(t) {
            return window.tdxEncrypt(t)
        }

在控制台输出加密函数window.tdxEncrypt,回车,定位到window.tdxEncrypt函数代码:
1666596909313.png
[JavaScript] 纯文本查看 复制代码
window.tdxEncrypt = function(r) {
        if (0 === r.indexOf("@ec0"))
            return r;
        r = e.encrypt(r += "@_bfstr");
        return "@ec0:" + e.base64Encode(r)
    }

再继续定位到e.encrypt函数代码:
1666597411162.png
[JavaScript] 纯文本查看 复制代码
encrypt: function(r, t) {
            if ("ecb" === this.mode)
                return this.encryptECB(r);
            if ("cbc" === this.mode)
                return this.encryptCBC(r, t);
            throw new Error("Неизвестный режим шифрования.")
        },

通过打断点进去,可以看见,this.mode=ecb,因此手机号是encryptECB加密函数:
[JavaScript] 纯文本查看 复制代码
encryptECB: function(r) {
            r = this.utf8Decode(r);
            for (var t = Math.ceil(r.length / 8), o = "", e = 0; e < t; e++) {
                var n = r.substr(8 * e, 8);
                if (n.length < 8)
                    for (var i = 8 - n.length; 0 < i--; )
                        n += "\0";
                var h = this.split64by32(n)
                  , s = h[0]
                  , u = h[1];
                s = (h = this.encipherEX(s, u))[0],
                u = h[1],
                o += this.num2block32(u) + this.num2block32(s)
            }
            return o
        },

再把涉及到的一些调用函数抠出来:
[JavaScript] 纯文本查看 复制代码
split64by32: function(r) {
            var t = r.substring(0, 4)
              , r = r.substring(4, 8);
            return [this.block32toNum(t), this.block32toNum(r)]
        },
        utf8Decode: function(r) {
            for (var t = "", o = 0; o < r.length; o++) {
                var e = r.charCodeAt(o);
                e < 128 ? t += String.fromCharCode(e) : (127 < e && e < 2048 ? t += String.fromCharCode(e >> 6 | 192) : (t += String.fromCharCode(e >> 12 | 224),
                t += String.fromCharCode(e >> 6 & 63 | 128)),
                t += String.fromCharCode(63 & e | 128))
            }
            return t
        },

encipherEX: function(r, t) {
            var o = this
              , t = t
              , r = o.xor(r = r, o.pArray[0])
              , t = o.round(t, r, 1);
            return r = o.round(r, t, 2),
            t = o.round(t, r, 3),
            r = o.round(r, t, 4),
            t = o.round(t, r, 5),
            r = o.round(r, t, 6),
            t = o.round(t, r, 7),
            r = o.round(r, t, 8),
            t = o.round(t, r, 9),
            r = o.round(r, t, 10),
            t = o.round(t, r, 11),
            r = o.round(r, t, 12),
            t = o.round(t, r, 13),
            r = o.round(r, t, 14),
            t = o.round(t, r, 15),
            [r = o.round(r, t, 16), t = o.xor(t, o.pArray[17])]
        },

xor: function(r, t) {
            return this.fixNegative(r ^ t)
        },
 trimZeros: function(r) {
            return r.replace(/\0+$/g, "")
        },
        wordbyte0: function(r) {
            return Math.floor(Math.floor(Math.floor(r / 256) / 256) / 256) % 256
        },
        wordbyte1: function(r) {
            return Math.floor(Math.floor(r / 256) / 256) % 256
        },
        wordbyte2: function(r) {
            return Math.floor(r / 256) % 256
        },
        wordbyte3: function(r) {
            return r % 256
        },
        round: function(r, t, o) {
            var e = this;
            return e.xor(r, e.xor(e.xor(e.sBox0[e.wordbyte0(t)] + e.sBox1[e.wordbyte1(t)], e.sBox2[e.wordbyte2(t)]) + e.sBox3[e.wordbyte3(t)], e.pArray[o]))
        },

o对象的值:
{
    "key": "w83c5~%%30nm5-+",
    "sBox0": [
        1401335157,
        2656414153,
        1572114622,
       这里还有,省略掉,太长了,
        839348932,
        2117317013,
        1753590868
    ],
    "sBox1": [
        2944530774,
        611268753,
        2480642903,
       这里还有,省略掉,太长了,
        1125867267
    ],
    "sBox2": [
        117595124,
        794470125,
        1939519107,
       这里还有,省略掉,太长了,
        1016397799,
        2504754504
    ],
    "sBox3": [
        898774924,
      这里还有,省略掉,太长了,
        35895393,
        1829467942
    ],
    "pArray": [
        4293367326,
        2903747409,
      这里还有,省略掉,太长了,
        1985119492
    ]
}

num2block32: function(r) {
            return String.fromCharCode(r << 24 >>> 24) + String.fromCharCode(r << 16 >>> 24) + String.fromCharCode(r << 8 >>> 24) + String.fromCharCode(r >>> 24)
        },

block32toNum: function(r) {
            return this.fixNegative(r.charCodeAt(3) << 24 | r.charCodeAt(2) << 16 | r.charCodeAt(1) << 8 | r.charCodeAt(0))
        },

fixNegative: function(r) {
            return r >>> 0
        },



base64Encode: function(r) {
            for (var t, o, e, n, i, h, s = "", u = 0; u < r.length; )
                e = (h = r.charCodeAt(u++)) >> 2,
                n = (3 & h) << 4 | (t = r.charCodeAt(u++)) >> 4,
                i = (15 & t) << 2 | (o = r.charCodeAt(u++)) >> 6,
                h = 63 & o,
                isNaN(t) ? i = h = 64 : isNaN(o) && (h = 64),
                s = s + this.keyStr.charAt(e) + this.keyStr.charAt(n) + this.keyStr.charAt(i) + this.keyStr.charAt(h);
            return s
        },

keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

把流程串起来之后得知手机号加密方式:
"@ec0:" + base64(encrypt(手机号+@_bfstr))
将js流程代码组装起来后验证如下:
[HTML] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<script type="text/javascript">
function num2block32(r) {
        return String.fromCharCode(r << 24 >>> 24) + String.fromCharCode(r << 16 >>> 24) + String.fromCharCode(r << 8 >>> 24) + String.fromCharCode(r >>> 24)
}

var o_data ={
    "key": "w83c5~%%30nm5-+",
    "sBox0": [
        1401335157,
        2656414153,
       这里还有,省略掉,太长了,
        839348932,
        2117317013,
        1753590868
    ],
    "sBox1": [
        2944530774,
        611268753,
        这里还有,省略掉,太长了,
        1410597869,
        1965163803,
        1125867267
    ],
    "sBox2": [
        117595124,
        794470125,
        这里还有,省略掉,太长了,
        1016397799,
        2504754504
    ],
    "sBox3": [
        898774924,
        3133324463,
        3959680370,
      这里还有,省略掉,太长了,
        35895393,
        1829467942
    ],
    "pArray": [
        4293367326,
        2903747409,
        2513112869,
       这里还有,省略掉,太长了,
        1985119492
    ]
}

function xor(r, t) {
        return fixNegative(r ^ t)
};


function trimZeros (r) {
        return r.replace(/\0+$/g, "")
};
function wordbyte0(r) {
        return Math.floor(Math.floor(Math.floor(r / 256) / 256) / 256) % 256
};
function wordbyte1(r) {
        return Math.floor(Math.floor(r / 256) / 256) % 256
};
function wordbyte2(r) {
        return Math.floor(r / 256) % 256
};
function wordbyte3 (r) {
        return r % 256
};
function round(r, t, o) {
        return xor(r, xor(xor(o_data.sBox0[wordbyte0(t)] + o_data.sBox1[wordbyte1(t)], o_data.sBox2[wordbyte2(t)]) + o_data.sBox3[wordbyte3(t)], o_data.pArray[o]))
};

function encipherEX(r, t) {
           t = t
          , r = xor(r = r, o_data.pArray[0])
          , t = round(t, r, 1);
        return r = round(r, t, 2),
        t = round(t, r, 3),
        r = round(r, t, 4),
        t = round(t, r, 5),
        r = round(r, t, 6),
        t = round(t, r, 7),
        r = round(r, t, 8),
        t = round(t, r, 9),
        r = round(r, t, 10),
        t = round(t, r, 11),
        r = round(r, t, 12),
        t = round(t, r, 13),
        r = round(r, t, 14),
        t = round(t, r, 15),
        [r = round(r, t, 16), t = xor(t, o_data.pArray[17])]
};
function fixNegative(r) {
        return r >>> 0
};
function block32toNum(r) {
        return fixNegative(r.charCodeAt(3) << 24 | r.charCodeAt(2) << 16 | r.charCodeAt(1) << 8 | r.charCodeAt(0))
};
function split64by32(r) {
        var t = r.substring(0, 4)
          , r = r.substring(4, 8);
        return [block32toNum(t), block32toNum(r)]
};

function utf8Decode(r) {
        for (var t = "", o = 0; o < r.length; o++) {
                var e = r.charCodeAt(o);
                e < 128 ? t += String.fromCharCode(e) : (127 < e && e < 2048 ? t += String.fromCharCode(e >> 6 | 192) : (t += String.fromCharCode(e >> 12 | 224),
                t += String.fromCharCode(e >> 6 & 63 | 128)),
                t += String.fromCharCode(63 & e | 128))
        }
        return t
};

function encryptECB(r) {
        r = utf8Decode(r);
        for (var t = Math.ceil(r.length / 8), o = "", e = 0; e < t; e++) {
                var n = r.substr(8 * e, 8);
                if (n.length < 8)
                        for (var i = 8 - n.length; 0 < i--; )
                                n += "\0";
                var h = split64by32(n)
                  , s = h[0]
                  , u = h[1];
                s = (h = encipherEX(s, u))[0],
                u = h[1],
                o += num2block32(u) + num2block32(s)
        }
        return o
};

var keyStr ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function base64Encode(r) {
        for (var t, o, e, n, i, h, s = "", u = 0; u < r.length; )
                e = (h = r.charCodeAt(u++)) >> 2,
                n = (3 & h) << 4 | (t = r.charCodeAt(u++)) >> 4,
                i = (15 & t) << 2 | (o = r.charCodeAt(u++)) >> 6,
                h = 63 & o,
                isNaN(t) ? i = h = 64 : isNaN(o) && (h = 64),
                s = s + keyStr.charAt(e) + keyStr.charAt(n) + keyStr.charAt(i) + keyStr.charAt(h);
        return s
};


debugger;

var aa = '15512345678'+'@_bfstr';
var bb = encryptECB(aa);
var cc = base64Encode(bb);
var dd = "@ec0:" + cc;
console.log(dd); //输出结果:@ec0:PvhToe2pW6FL0v1tQru05UKrc5uZJHC5,与抓包数据一致

</script>                
</body>
</html>


密码的加密方式、以及返回值的解密方式,也能通过相同的方法获取到对应的处理方案。
















结帖率:90% (27/30)

签到天数: 18 天

发表于 2024-1-19 22:25:17 | 显示全部楼层   山东省济宁市
多谢分享
回复 支持 反对

使用道具 举报

签到天数: 4 天

发表于 2023-1-13 09:37:15 | 显示全部楼层   广东省湛江市
感谢楼主分享
回复 支持 反对

使用道具 举报

发表于 2022-11-14 08:07:15 | 显示全部楼层   四川省泸州市
感谢楼主分享
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)
发表于 2022-11-5 14:06:02 | 显示全部楼层   山东省菏泽市
有用的知识增加了!~  
回复 支持 反对

使用道具 举报

结帖率:75% (3/4)
发表于 2022-11-4 14:59:38 | 显示全部楼层   北京市北京市
会的看不上,不会的看不懂
回复 支持 反对

使用道具 举报

签到天数: 2 天

发表于 2022-10-25 04:39:48 | 显示全部楼层   广西壮族自治区钦州市
会的看不上,不会的看不懂
回复 支持 反对

使用道具 举报

结帖率:90% (27/30)

签到天数: 17 天

发表于 2022-10-24 20:56:27 | 显示全部楼层   广东省佛山市
好厉害啊,大神,可惜我看不懂
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表