文章目录
概要
提示:仅供学习,不得用做商业交易,如有侵权请及时联系
逆向: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")]("_"))
分析这块代码
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
-
最后再说一下这个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)