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有值的话,我们可以给它赋值字符串,重新生成一个
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加密
const CryptoJs = require('crypto-js');
var getReportUrl_metricCount = 0var 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
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就是加密函数
var x = {data: b(e, r, Zc)[n("0xf")](e, t),appName: at[n("0x19")]()};
8、进入到加密函数,我们观察可以看到,mc也是一个AES,key的值是:“Q5eV2XXICMBi0CBL”,但是它是ECB模式的,需要注意一下,肯定也是对toString进行了魔改的
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数组,这里其实就是一个字符串压缩算法
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
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)