首页 文章详情

Python 爬虫进阶必备 | 某小众商城 h5 商品列表页加密参数逻辑分析

咸鱼学Python | 393 2021-10-14 21:25 0 0 0
UniSMS (合一短信)
点击上方“咸鱼学Python”,选择“加为星标

第一时间关注Python技术干货!


图源:极简壁纸


今日网站

aHR0cHM6Ly9oNS53YW53dWRlemhpLmNvbS9tYWxsLXdlYi9jYXRlZ29yeS9jbGFzc2lmeS8xNjE5MTYxNDM3NDMxP3RleHQ9JUU2JTg5JThCJUU0JUI4JUIyJmNpZD0xMCZmYWNhZGVDYXRlZ29yeUlkPTEwJmlzU2hvd0F1Y3Rpb25GaXJzdD0xJl9fSGdXdHdZVT0xNjE5MTYxNDM3NDMxJnJ0cFJlZmVyPWJ3MC53MC4wLjAuMTYxOTE2MTQzNTQ4MiUyNEc3SiZzaGFyZVVzZXJJZD0xODc1OTU4OCZzaGFyZVRpbWU9MTU5MTY5MDY5OSZydHBBcHBsaWNhdGlvbj1INS5VWEdCdVR4ZloxNjMzMDg4OTQzMDcw

这个网站需要分析的参数较多,一个个来

抓包分析与加密定位

像这种下拉刷新的看抓包直接切换到xhr里就可以看到了

可以看到上述图片的请求头的位置都是需要分析的值

分析下以下几个参数,分别是kl_signkl_device_idkl_trace_id

接下来一个个分析他们的加密逻辑

加密定位与分析

kl_device_id

直接检索只有一项,并且在结果项中再检索也只有一个匹配项

function he(t{
    if (!t)
        return s[64];
    for (var e = "", r = 92132, n = s[65]; n < t.length; n++) {
        var i = t.charCodeAt(n) ^ r;
        r = r * n % 256 + a[4],
            e += String.fromCharCode(i)
    }
    return e
}

这里传入的参数是两个特殊的编码

特殊编码在编辑器里经常会因为我们在运行代码的时候的编码转换出现问题,所以可以在传参的时候先 base64 编码一下,然后在接收的时候解码避免因为编码不同导致的各种问题

kl_trace_id

这里的 trace_id 就在device_id的下边

然后这里的调用了Qr[a[194]]的逻辑,在控制台输出一下,点击回显跳转过去

m = function({
    var t = (new Date).getTime();
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function(e{
        var r = (t + 16 * Math.random()) % 16 | 0;
        return t = Math.floor(t / 16),
            ("x" === e ? r : 3 & r | 8).toString(16)
    }))
}

就是根据时间戳随机生成的uuid

kl_sign

这个参数没有上面的参数放在一块所以单独找找看看

直接检索是没有结果的,但是肯定是和上面几个参数一块提交的

所以我们继续下一步分析看看

所以需要分析的参数kl_sign就是R

这里的R

R = Yr.a[de("%\\_Y")](d, j, C)

所以对以上的参数一个个分析

这里的C是一个Map对象,里面有kl_pathkl_trace_idkl_device_id

除了kl_path之外其他两个都已经找到生成的逻辑了

kl_path是一个固定值没有太多分析的必要

d时间戳/1000,现在还剩一个j,这里的j是提交的参数

所以现在需要分析的回到上面又变成了Yr.a[de("%\\_Y")]这个加密方法是什么?

所以重新断点进去看看加密

这里返回的是oe

接下来继续一步步跟

单步到oe里看到这里就是直接返回了一个方法,可以看到好大一串

所以继续找这个返回的方法的返回值

ee[Jt(s[57])][$t(bt + r + "REDAE" + n + i + o)] + "=" + ee[te("d?RVg7GYZ[MZ%")].ALGORITHM + u[58] + ee[Jt("涐淹涞淰涠淁涳淒涿淺涔淡涌淿")][wt + "ER_SIGNEDHEADERS"] + "=" + m[Jt("涷淘涋淿涍淤涊" + p)]() + te("") + ee[$t(d + "raPngiS")][St + "IONHEADER_" + b] + $t(u[59]) + O + $t("/") + ee[h[67]]["AUTHORIZATION" + g + xt] + a[63] + A

就是上面一串

这一串有很多的未知参数,所以先剔除一些固定值,并且把里面混淆的乱码啥的去掉

可以看到通过一个个分析有很多的固定参数,所以我们不用分析

主要分析的变成了最后最后的A

前面的O是时间戳+_wwdz_request的字符串

O = t[te('C?X]D"TUG')] + "_" + ee[y + "Enums"][a[62]];

这里的A在上面的方法返回

混淆还原之后是下面这样的代码

var A = function(t, e{
    var r, n = "od", i = "s", o = "s", p = "SIGNEDPARAM_T", d = 'ums', g = h[80], v = "SIGNEDPARAM_S", m = new Map, y = at['MD5'](ee.SignParamEnums.SIGNSECRETKEY + ee.SignParamEnums.SIGNSALT + t.signVersion)["toString"](), b = it(e);
    try {
        for (b.s(); !(r = b['n']())['done']; ) {
            var E = r["value"];
            m.set(E[0], E[1])
        }
    } catch (t) {
        b.e(t)
    } finally {
        b['f']()
    }
    return m['set'](ee['SignParamEnums']['SIGNEDPARAM_SID'], t['sId']),
        m['set'](ee['SignParamEnums']['SIGNEDPARAM_TIMESTAMP'], t['timestamp']),
        m['set'](ee['SignParamEnums']['SIGNEDPARAM_APPVERSION'], t['appVersion']),
        m['set'](ee['SignParamEnums']['SIGNEDPARAM_SIGNVERSION'], t['signVersion']),
        m['set'](ee.SignParamEnums['SIGNEDPARAM_PAYLOAD'], function(t, e{
        return at['HmacSHA256'](t, e)['toString']()
    }(t['payload'], y)),
        function(t, e{
        var r = st.getParamStr(t);
        return r = r.toUpperCase(),
            at.HmacSHA256(r, e).toString()
    }(m, y)
}(t, e)

可以看到大致就是对时间戳和上面分析到的几个参数进行hash,并且在最后还用了sha256对提交参数进行取值,完成最后的加密

而具体流程是这样的

在开始的定义参数的位置先对下面的几个参数进行 hash

Md5 的参数是取得下面的几个参数拼接的结果

ee.SignParamEnums.SIGNSECRETKEY + ee.SignParamEnums.SIGNSALT + t.signVersion
# 'bbcc71f7b26a82ea97196366558a8ef0e680d60e7e6bd5931cb46d30c91d6d0d1.0.0'

然后下面有一个 Map

其中在 Map 的 PAYLOAD 传入下面代码计算出来的值

function(t, e{
    return at["sha256"](t, e)["toString"]()
}(t["payloa" + v], y))

这里的y是上面hash的结果,另一个参数是请求提交的参数

'{"orderType":4,"facadeCategoryId":88,"type":0,"pageIndex":6,"pageSize":20,"facadeStr":"{\"facadeCategoryId\":88,\"icon\":\"https://cdn.wanwudezhi.com/seller-admin/image/MTYyODI1NzIwODI2Mg==608_408x408.png\",\"name\":\"全部\"}"}'

这两个参数传入进去之后,经过了sha256的处理

最后 Map 和上面的 y也就是上面 md5 的结果再进行一次sha256就是最后需要的参数A

这个时候Map需要先经过一个方法getParamStr

这个getParamStr是将这个 Map 的键值用=拼接起来并大写

结果是这样的

'APPVERSION=4.2.2&KL_DEVICE_ID=929297D0-22AD-11EC-8138-2F372015C114&KL_PATH=/ACTIVITYSEARCH/CATEGORY/ITEM&KL_TRACE_ID=398B3426-DA81-4C7B-8814-262E71E16D0C&PAYLOAD=6E38BB8B8405042A505B761B1BF2BF0BBD8BBB968A24FB6F0FF3DF4A89D6427A&SID=300100&SIGNVERSION=1.0.0&TIMESTAMP=1633100416'

然后将这个值和y sha256 得到最后的结果

这个站的加密不难就是恶心,很多逻辑都混淆过,就是让你看起来麻烦

好了,以上就是今天的全部内容了。

我是没有更新就在摸鱼的咸鱼

收到请回复~

我们下次再见。

对了,看完记得一键四连,这个对我真的很重要。

good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter