JS逆向 - (国外)SHEIN站 - 请求头(armorToken、Anti-in)

文章目录

概要

提示:仅供学习,不得用做商业交易,如有侵权请及时联系

逆向:JS逆向 - (国外)SHEIN站 - 请求头(armorToken、Anti-in)
URL:aHR0cHM6Ly9pZC5zaGVpbi5jb20vUmVjb21tZW5kU2VsZWN0aW9uL0hvbWUtS2l0Y2hlbi1zYy0wMTcxODU1NDYuaHRtbD9pY2k9aWRlbl90YWIwNW5hdmJhcjA1JnNyY19tb2R1bGU9dG9wY2F0JnNyY19pZGVudGlmaWVyPWZjJTNESG9tZSUyMCUyNiUyMEtpdGNoZW4lNjBzYyUzREhvbWUlMjAlMjYlMjBLaXRjaGVuJTYwdGMlM0QwJTYwb2MlM0QwJTYwcHMlM0R0YWIwNW5hdmJhcjA1JTYwamMlM0RpdGVtUGlja2luZ18wMTcxODU1NDYmc3JjX3RhYl9wYWdlX2lkPXBhZ2VfaG9tZTE3NTAzMTk2NDQ2NzQmY2F0ZWdvcnlKdW1wPTY2MTE3MV8hXzAmcGFnZT0y

提示:需要翻墙

整体架构流程

提示:分析参数生成

1、参数位置和验证接口:

响应内容:会返回一个token

2、堆栈分析位置或者搜索关键字:armorToken,这里就不带着一起跟了,直接搜索


提示:需要将浏览器加载的缓存全部清理

3、下断,直接刷新网页,NcWc("0x3c")跳进去吗,发现是从zc函数进行加密的


注意:手动去执行它加密的时候,浏览器会将生成好的值存储到localStorage/sessionStorage
4、进入到zc函数,我们可以看到,如果$c这个对象里面的value有值的话,我们可以给它赋值字符串,重新生成一个

javascript 复制代码
w(this, Rc, $c, [["S", at[t("0x11")]()][t("0x51")](""), pt(), te[t("0x22")](mc[t("0x4e")](Dn[t("0x4f")](b(this, Rc, Kc)[t("0xf")](this)), Dn[t("0x4f")](At()), {
                iv: J[t("0x4f")](""),
                mode: L[t("0x5c")][t("0x5d")],
                padding: Pc
            })[t("0x50")]), (new Date)[t("0x5e")]()][t("0x51")]("_"))

分析这块代码

  • att("0x11"):固定、pt():版本号

  • b(this, Rc, Kc)t("0xf"):这里观察是下面的Kc函数获取,Qr就是一个标准的MD5加密

javascript 复制代码
const CryptoJs = require('crypto-js');
var getReportUrl_metricCount = 0
    var version = "3.7.0"
    var armorUuid = '浏览器返回'
    var userAgent = "换成自己的"
    var now_time = new Date().getTime()
    get8LRandomStr = function () {
        return 'xxxxxxxx'['replace'](/[xy]/g, (function (t) {
            var n = 16 * Math["random"]() | 0;
            return ("x" == t ? n : 3 & n | 8)['toString'](16)
        }
        ))
    }();

    armorToken_list = [getReportUrl_metricCount, version, armorUuid, userAgent, now_time, get8LRandomStr, '-'].join("^@^")
    armorToken_list_data = [armorToken_list, CryptoJs.MD5(armorToken_list).toString()["slice"](-6)].join("^@^")
  • 继续看一下key是什么:发现是固定的"Yp22&mqMv#3t28Zh"

  • 继续观察它是一个AES加密,并且是标准的,但是转字符串的函数是魔改的 ,你会看到AES加密其实取的是ciphertext

javascript 复制代码
CryptoJs.enc.toString_ = function toString(t) {
    var r = !0;
    var e = t["words"]
        , x = t["sigBytes"]
        , a = r ? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    t["clamp"]();
    for (var i = [], o = 0; o < x; o += 3)
        for (var c = (e[o >>> 2] >>> 24 - o % 4 * 8 & 255) << 16 | (e[o + 1 >>> 2] >>> 24 - (o + 1) % 4 * 8 & 255) << 8 | e[o + 2 >>> 2] >>> 24 - (o + 2) % 4 * 8 & 255, u = 0; u < 4 && o + .75 * u < x; u++)
            i["push"](a['charAt'](c >>> 6 * (3 - u) & 63));
    var s = a['charAt'](64);
    if (s)
        for (; i['length'] % 4; )
            i["push"](s);
    return i['join']("")
}
aes_encrypt = function (data, key, iv) {
    key = CryptoJs.enc.Utf8.parse(key);
    iv = CryptoJs.enc.Utf8.parse(iv);
    var encrypted = CryptoJs.AES.encrypt(data, key, {
        iv: iv,
        mode: CryptoJs.mode.CBC,
        padding: CryptoJs.pad.Pkcs7
    });
    return CryptoJs.enc.toString_(encrypted.ciphertext);
}

最后将上面的值进行拼接就得到了armorToken
7、继续分析我们的第二个参数Anti-in,这里划一下水,自己跟一下栈,比较容易跟

你会发现它是通过浏览器指纹进行加密最好得到一大串字符串的,这里Zc就是加密函数

javascript 复制代码
var x = {
                        data: b(e, r, Zc)[n("0xf")](e, t),
                        appName: at[n("0x19")]()
                    };

8、进入到加密函数,我们观察可以看到,mc也是一个AES,key的值是:"Q5eV2XXICMBi0CBL",但是它是ECB模式的,需要注意一下,肯定也是对toString进行了魔改的

javascript 复制代码
aes_encrypt_Ecb = function (data, key) {
    key = CryptoJs.enc.Utf8.parse(key);
    var encrypted = CryptoJs.AES.encrypt(data, key, {
        mode: CryptoJs.mode.ECB,
        padding: CryptoJs.pad.Pkcs7
    });
    return encrypted.ciphertext;
}
  • 这里我们会发现i的值就是对指纹数组进行转字符串,然后先经过oc处理这个字符串得到一个Uint8Array数组,这里其实就是一个字符串压缩算法
javascript 复制代码
const pako = require('pako');
const encoder = new TextEncoder();
const utf8Bytes = encoder.encode(指纹字符串);
const compressedBytes = pako.deflate(utf8Bytes);  // 默认生成 zlib 头 
const zhiw_stringify_uint8Array = new Uint8Array(compressedBytes);
  • 继续我们看到,对这个压缩后的数组进行转WrodArry,其实这个J[r("0x49")]函数就是标准的CryptoJs.enc.Hex.parse

  • Qr(i)n("0xc")n("0x4d"):说一下这里其实也是对指纹进行MD5然后取后面6位

  • 最后再说一下这个Mc(u, Tc):它也是一个魔改的stringify

javascript 复制代码
function Tc(t, r) {
        return 64 === t ? 64 : 63 === t ? r : t >= r ? t + 1 : t
 }
function Mc(t, n) {
    var e = t["words"]
      , x = t["sigBytes"]
      , i = "xYACKb9gwIn12kHtuiG7RVSJjTU-Z8cq_NOvmXzeaFoyWQpDh3LB4rs0EM6fd5lP=";
    t["clamp"]();
    for (var a = [], o = Math["floor"](64 * Math["random"]()), u = 0; u < x; u += 3)
        for (var c = (e[u >>> 2] >>> 24 - u % 4 * 8 & 255) << 16 | (e[u + 1 >>> 2] >>> 24 - (u + 1) % 4 * 8 & 255) << 8 | e[u + 2 >>> 2] >>> 24 - (u + 2) % 4 * 8 & 255, s = 0; s < 4 && u + .75 * s < x; s++) {
            var f = c >>> 6 * (3 - s) & 63;
            a['push'](i['charAt'](n(f, o)))
        }
    var v = i['charAt'](64);
    if (v)
        for (; a['length'] % 4; )
            a['push'](v);
    return a['join']("")['replace'](/=/g, "") + i[o]
}

技术名词解释

提示:py调用

小结

提示:学习交流主页,星球持续更新中:链接https://t.zsxq.com/AJTw2(+星球主页+v)

相关推荐
yvvvy6 分钟前
从“按钮都不会点”到“能撸大厂 UI”:我用 react-vant 踢开组件库的大门!
前端·javascript
安然dn7 分钟前
Cropper.js:JS图像裁剪库
前端·javascript
Danny_FD40 分钟前
Vue + Element UI 实现模糊搜索自动补全
前端·javascript
gnip1 小时前
闭包实现一个简单Vue3的状态管理
前端·javascript
Enddme1 小时前
《面试必问!JavaScript 中this 全方位避坑指南 (含高频题解析)》
前端·javascript·面试
赵英英俊1 小时前
Python day26
开发语言·python
你怎么知道我是队长1 小时前
python---eval函数
开发语言·javascript·python
用户2519162427111 小时前
Canvas之图像合成
前端·javascript·canvas
Mintopia2 小时前
🎯 光与面的命运交锋:Möller-Trumbore 线段三角形相交算法全解析
前端·javascript·计算机图形学
Rockson2 小时前
期货实时行情接口接入教程
python·api