在逆向某网站时遇到其设置的cookie名为alicfw, 当用户访问次数过大时,无论get还是post访问其网站域名都会返回一个html而非想要的数据,这个html里仅包括两个html参数和一段巨长的混淆后的JavaScript代码,会JavaScript检查了windows location document并为用户设置cookie,从而实现反爬。如果没有逆向出来后续一段时间内访问结果将一直是该html。逆向难度不大,其仅使用了简单的混淆和简单的加密函数
由于其源js文件过长,放在最后。这里仅展示解混淆后的结果
我这里使用的解混淆办法是chrome的插件v_jstools,其效果如下
选择打开配置页面,进入解混淆页面,在source里粘贴JavaScript代码部分,然后解密ob高级混淆,即可看到结果
其解混淆后的代码如下所示
function hash32(M, B, j, f, N, j) {
f = (f ^ 1328233025) >>> 0;
N = (N ^ 1328233025) >>> 0;
var W = M + "&" + B + "&" + j + "&" + f + "&" + N;
var I;
var A;
var C;
var b;
var T;
var x;
var l;
var P;
var d;
var s;
seed = j % 2061440;
I = W.length & 3;
A = W.length - I;
C = seed;
T = 3432918353;
l = 461845907;
s = 0;
while (s < A) {
d = W.charCodeAt(s) & 255 | (W.charCodeAt(++s) & 255) << 8 | (W.charCodeAt(++s) & 255) << 16 | (W.charCodeAt(++s) & 255) << 24;
++s;
d = (d & 65535) * T + (((d >>> 16) * T & 65535) << 16) & 4294967295;
d = d << 15 | d >>> 17;
d = (d & 65535) * l + (((d >>> 16) * l & 65535) << 16) & 4294967295;
C ^= d;
C = C << 13 | C >>> 19;
b = (C & 65535) * 5 + (((C >>> 16) * 5 & 65535) << 16) & 4294967295;
C = (b & 65535) + 27492 + (((b >>> 16) + 58964 & 65535) << 16);
}
d = 0;
switch (I) {
case 3:
d ^= (W.charCodeAt(s + 2) & 255) << 16;
case 2:
d ^= (W.charCodeAt(s + 1) & 255) << 8;
case 1:
d ^= W.charCodeAt(s) & 255;
d = (d & 65535) * T + (((d >>> 16) * T & 65535) << 16) & 4294967295;
d = d << 15 | d >>> 17;
d = (d & 65535) * l + (((d >>> 16) * l & 65535) << 16) & 4294967295;
C ^= d;
}
return C ^= W.length, C ^= C >>> 16, C = (C & 65535) * 2246822507 + (((C >>> 16) * 2246822507 & 65535) << 16) & 4294967295, C ^= C >>> 13, C = (C & 65535) * 3266489909 + (((C >>> 16) * 3266489909 & 65535) << 16) & 4294967295, C ^= C >>> 16, result = (C >>> 0) + "|" + j + "|" + f + "|" + N, result;
}
function setCookie(M, B) {
var W = new Date();
var A = "alicfw";
var r = "alicfw_gfver";
var C = "v1.200309.1";
W.setDate(W.getDate() + B);
if ("https:" === document.location.protocol) {
var I = !![];
} else {
var I = ![];
}
if (I) {
document.cookie = A + "=" + escape(M) + (B == null ? "" : ";expires=" + W.toGMTString()) + ";path=/" + ";samesite=none;secure";
document.cookie = r + "=" + escape(C) + (B == null ? "" : ";expires=" + W.toGMTString()) + ";path=/" + ";samesite=none;secure";
} else {
document.cookie = A + "=" + escape(M) + (B == null ? "" : ";expires=" + W.toGMTString()) + ";path=/";
document.cookie = r + "=" + escape(C) + (B == null ? "" : ";expires=" + W.toGMTString()) + ";path=/";
}
}
function check() {
console.log(document.location.protocol);
console.log(document.cookie);
var W = window.location.host;
var f = document.documentElement.clientWidth;
var N = document.documentElement.clientHeight;
var r = document.getElementById("parm_0").value;
var I = document.getElementById("parm_1").value;
var A = hash32(W, r, I, f, N, I);
setCookie(A, 1);
window.location.reload(!![]);
}
函数名变量名已经很明确了,显然看到JavaScript加密的关键就是函数hash32,其接收五个参数,host、屏幕宽高、两个html元素input里的值,进行复现即可
跟着原hash32函数一步步走即可
我复现的代码如下:
其中的int_overflow和unsinged_right_shift我稍后解释
def hash32(host, value_1, value_2, width, height):
width = (width ^ 1328233025) & 0xFFFFFFFF
height = (height ^ 1328233025) & 0xFFFFFFFF
W = f"{host}&{value_1}&{value_2}&{width}&{height}"
print("W:", W)
seed = value_2 % 2061440
I = len(W) & 3
A = len(W) - I
C = seed
T = 3432918353
l = 461845907
s = 0
print("seed", seed)
while s < A:
d = (ord(W[s]) & 0xFF) | ((ord(W[s + 1]) & 0xFF) << 8) | ((ord(W[s + 2]) & 0xFF) << 16) | (
(ord(W[s + 3]) & 0xFF) << 24)
s += 4 # 注意js中是++s,上方加了三次
d = (d & 0xFFFF) * T + ((((d >> 16) & 0xFFFF) * T & 0xFFFF) << 16) & 4294967295
d = int_overflow(d << 15) | unsinged_right_shift(d, 17)
d = (d & 0xFFFF) * l + int_overflow(((((d >> 16) & 0xFFFF) * l & 0xFFFF) << 16) & 4294967295)
d = int_overflow(d)
C ^= d
C = int_overflow(C << 13) | unsinged_right_shift(C, 19)
b = (C & 0xFFFF) * 5 + int_overflow((unsinged_right_shift(C, 16) * 5 & 65535) << 16) & 4294967295
b = int_overflow(b)
C = (b & 0xFFFF) + 27492 + int_overflow(int_overflow((unsinged_right_shift(b, 16) + 58964) & 65535) << 16)
d = 0
if I == 3:
d ^= int_overflow((ord(W[s + 2]) & 255) << 16)
if I >= 2:
d ^= int_overflow((ord(W[s + 1]) & 255) << 8)
if I >= 1:
d ^= ord(W[s]) & 255
d = (d & 0xFFFF) * T + int_overflow((unsinged_right_shift(d, 16) * T & 0xFFFF) << 16) & 4294967295
d = int_overflow(d << 15) | unsinged_right_shift(d, 17)
d = (d & 0xFFFF) * l + int_overflow((unsinged_right_shift(d, 16) * l & 0xFFFF) << 16) & 4294967295
C ^= d
C ^= len(W)
C ^= unsinged_right_shift(C, 16)
C = int_overflow((C & 0xFFFF) * 2246822507) + (
int_overflow((unsinged_right_shift(C, 16) * 2246822507 & 65535) << 16) & 0xFFFF0000)
C ^= unsinged_right_shift(C, 13)
C = int_overflow((C & 0xFFFF) * 3266489909) + (
int_overflow((unsinged_right_shift(C, 16) * 3266489909 & 65535) << 16) & 0xFFFF0000)
C ^= C >> 16
result = f"{C & 0xFFFFFFFF}|{value_2}|{width}|{height}"
return result
我在使用时一开始计算出的值始终与浏览器结果不匹配,后来debug发现浏览器端计算时大量用到无符号数右移和溢出情况,这在python中是没有的因此有些负数不会产生,需要手动编写函数实现,因此我编写了下面两个函数实现类似效果:
import ctypes
def unsinged_right_shift(x, y):
x, y = ctypes.c_uint32(x).value, y % 32
return ctypes.c_uint32(x >> y).value
def int_overflow(val):
maxint = 2147483647
if not -maxint - 1 <= val <= maxint:
val = (val + (maxint + 1)) % (2 * (maxint + 1)) - maxint - 1
return val
最后封装一个函数,传入html原生文本,输出alicfw参数,我的实现方法如下:
def generate_alicfw(html_text: str):
content = html_text.split('\n')
value_1 = content[2].split('value=')[1].split(' id=')[0]
value_2 = content[3].split('value=')[1].split(' id=')[0]
alicfw = hash32(
host="www.xxxxxx.com",
width=1920,
height=1080,
value_1=int(value_1),
value_2=int(value_2)
)
return alicfw
<html>
<body onload="check()">
<input type="hidden" name="parm_0" value=1870201778 id="parm_0">
<input type="hidden" name="parm_1" value=2016818580 id="parm_1">
<script type="text/javascript">
function Z() {
var U = ['setDate', 'CPBoA', 'EuWuh', '2692915LPvLJc', 'EyJtp', 'BnmBC', 'alicfw', 'wAXWR', 'toGMTString', 'ZCtne', 'dRcWF', 'WPKcA', 'gsyGC', 'VdsWn', 'VOeWP', 'vkRGS', 'PKfKs', 'VIwmN', 'clientHeight', 'qGSHB', '6|2|0|4|7|8|1|3|5', '2382APyAnZ', 'eOxRB', 'NaTvv', 'aKLEt', 'getDate', 'JjGpV', 'location', 'uOefP', 'length', 'szlwY', 'cookie', 'WHFvT', 'host', 'wiGeS', '353784PLKrwL', 'BUlET', ';path=/', 'NQYEZ', 'tmuPq', 'CyuZJ', 'protocol', 'split', 'reRGP', 'KdxMP', 'SLEuY', 'NRYtj', 'bGnGz', 'LRjWH', 'ngiRp', 'clientWidth', 'MeUzm', 'mGkxk', '11511150QPbmwW', '144ZPJzag', '1914666ufUThb', 'auTOZ', '1082904JoefgG', 'getElementById', 'YPShL', 'log', 'YNynO', 'mTySG', ';expires=', '3880AlRztD', 'NNQHb', '5|4|6|0|2|3|8|9|7|1', 'dLMKj', 'v1.200309.1', 'FLGyw', ';samesite=none;secure', 'bFSkT', 'zlyUs', 'ugWJY', 'Fbuli', 'ABLuu', 'fpiQy', 'RvZLO', 'vNwPb', 'DjXXN', 'hZCEl', 'https:', 'fyoal', 'dPGFj', '2|5|0|6|1|4|3', 'GiIZm', 'charCodeAt', 'alicfw_gfver', 'fzCyE', 'value', 'ubdGA', 'BEMgz', 'DHkIL', 'LzWrw', 'reload', 'parm_0', '1294479RTlfGo', 'VDyTo', 'ysIEr', '14CZcKYt'];
Z = function() {
return U;
}
;
return Z();
}
(function(M, B) {
var V = a
, j = M();
while (!![]) {
try {
var f = -parseInt(V(0x112)) / 0x1 + parseInt(V(0x14d)) / 0x2 + -parseInt(V(0x12b)) / 0x3 * (parseInt(V(0x156)) / 0x4) + parseInt(V(0x119)) / 0x5 + parseInt(V(0x14f)) / 0x6 * (-parseInt(V(0x115)) / 0x7) + -parseInt(V(0x139)) / 0x8 * (-parseInt(V(0x14c)) / 0x9) + parseInt(V(0x14b)) / 0xa;
if (f === B)
break;
else
j['push'](j['shift']());
} catch (N) {
j['push'](j['shift']());
}
}
}(Z, 0xe2ccc));
function hash32(M, B, j, f, N, j) {
var h = a
, r = {
'PKfKs': function(g, z) {
return g >>> z;
},
'qGSHB': function(g, z) {
return g ^ z;
},
'tmuPq': function(g, z) {
return g + z;
},
'GiIZm': function(g, z) {
return g + z;
},
'JjGpV': function(g, z) {
return g % z;
},
'CPBoA': function(g, z) {
return g & z;
},
'eOxRB': function(g, z) {
return g - z;
},
'XBRlp': h(0x12a),
'NaTvv': function(g, z) {
return g * z;
},
'KdxMP': function(g, z) {
return g << z;
},
'LzWrw': function(g, z) {
return g & z;
},
'CyuZJ': function(g, z) {
return g >>> z;
},
'ZCtne': function(g, z) {
return g | z;
},
'dLMKj': function(g, z) {
return g << z;
},
'gsyGC': function(g, z) {
return g >>> z;
},
'BEMgz': function(g, z) {
return g + z;
},
'VOeWP': function(g, z) {
return g * z;
},
'XigdA': function(g, z) {
return g >>> z;
},
'SLEuY': function(g, z) {
return g << z;
},
'igwtY': function(g, z) {
return g >>> z;
},
'wAXWR': function(g, z) {
return g + z;
},
'auTOZ': function(g, z) {
return g & z;
},
'ngiRp': function(g, z) {
return g >>> z;
},
'vNwPb': function(g, z) {
return g & z;
},
'YPShL': function(g, z) {
return g & z;
},
'bGnGz': function(g, z) {
return g << z;
},
'BnmBC': function(g, z) {
return g & z;
},
'jpGYf': function(g, z) {
return g + z;
},
'ugWJY': function(g, z) {
return g & z;
},
'DjXXN': function(g, z) {
return g + z;
},
'wgyga': function(g, z) {
return g & z;
},
'aKLEt': function(g, z) {
return g >>> z;
},
'LRjWH': function(g, z) {
return g | z;
},
'PAqHz': function(g, z) {
return g >>> z;
},
'qltHb': function(g, z) {
return g + z;
},
'bFSkT': function(g, z) {
return g * z;
},
'ABLuu': function(g, z) {
return g >>> z;
},
'szlwY': function(g, z) {
return g * z;
},
'reRGP': function(g, z) {
return g >>> z;
},
'BUlET': function(g, z) {
return g >>> z;
},
'fpiQy': function(g, z) {
return g & z;
},
'EuWuh': function(g, z) {
return g + z;
},
'VdsWn': function(g, z) {
return g & z;
},
'NQYEZ': function(g, z) {
return g & z;
},
'WPKcA': function(g, z) {
return g * z;
},
'jHvVc': function(g, z) {
return g >>> z;
},
'fyoal': function(g, z) {
return g + z;
},
'dPGFj': function(g, z) {
return g + z;
},
'NNQHb': function(g, z) {
return g + z;
}
};
f = r['PKfKs'](f ^ 0x4f2b3a41, 0x0),
N = r[h(0x129)](N, 0x4f2b3a41) >>> 0x0;
var W = r[h(0x13d)](r[h(0x13d)](r[h(0x13d)](r[h(0x13d)](r[h(0x107)](M + '&' + B + '&', j), '&'), f), '&'), N), I, A, C, b, T, x, l, P, d, s;
seed = r[h(0x130)](j, 0x1f7480),
I = r[h(0x117)](W[h(0x133)], 0x3),
A = r[h(0x12c)](W[h(0x133)], I),
C = seed,
T = 0xcc9e2d51,
l = 0x1b873593,
s = 0x0;
while (s < A) {
var u = r['XBRlp'][h(0x140)]('|')
, p = 0x0;
while (!![]) {
switch (u[p++]) {
case '0':
d = r[h(0x107)](r['NaTvv'](r[h(0x117)](d, 0xffff), T), r['KdxMP'](r[h(0x10f)](r[h(0x12d)](r[h(0x13e)](d, 0x10), T), 0xffff), 0x10)) & 0xffffffff;
continue;
case '1':
C = r[h(0x11f)](r[h(0xf5)](C, 0xd), r[h(0x122)](C, 0x13));
continue;
case '2':
++s;
continue;
case '3':
b = r['LzWrw'](r[h(0x10d)](r[h(0x124)](r[h(0x10f)](C, 0xffff), 0x5), r[h(0xf5)](r['XigdA'](C, 0x10) * 0x5 & 0xffff, 0x10)), 0xffffffff);
continue;
case '4':
d = r[h(0x143)](d, 0xf) | r['igwtY'](d, 0x11);
continue;
case '5':
C = r[h(0x11d)](r[h(0x13d)](r[h(0x10f)](b, 0xffff), 0x6b64), r['auTOZ'](r[h(0x13d)](r[h(0x147)](b, 0x10), 0xe654), 0xffff) << 0x10);
continue;
case '6':
d = r['ZCtne'](W[h(0x108)](s) & 0xff, r[h(0x100)](W[h(0x108)](++s), 0xff) << 0x8) | r[h(0x142)](W[h(0x108)](++s) & 0xff, 0x10) | r[h(0x143)](W[h(0x108)](++s) & 0xff, 0x18);
continue;
case '7':
d = r[h(0x151)](r[h(0x13d)](r[h(0x124)](d & 0xffff, l), r[h(0x143)](r[h(0x12d)](r[h(0x126)](d, 0x10), l) & 0xffff, 0x10)), 0xffffffff);
continue;
case '8':
C ^= d;
continue;
}
break;
}
}
d = 0x0;
switch (I) {
case 0x3:
d ^= r[h(0x145)](r[h(0x11b)](W[h(0x108)](r['jpGYf'](s, 0x2)), 0xff), 0x10);
case 0x2:
d ^= r['dLMKj'](r['vNwPb'](W[h(0x108)](s + 0x1), 0xff), 0x8);
case 0x1:
d ^= r[h(0xfb)](W[h(0x108)](s), 0xff),
d = r[h(0x11b)](r[h(0x101)](r[h(0x12d)](r['wgyga'](d, 0xffff), T), r[h(0x143)](r[h(0x12e)](d, 0x10) * T & 0xffff, 0x10)), 0xffffffff),
d = r[h(0x146)](d << 0xf, r['PAqHz'](d, 0x11)),
d = r['qltHb'](r[h(0xf9)](r[h(0x14e)](d, 0xffff), l), r[h(0x142)](r[h(0xfd)](d, 0x10) * l & 0xffff, 0x10)) & 0xffffffff,
C ^= d;
}
return C ^= W[h(0x133)],
C ^= C >>> 0x10,
C = r[h(0x10f)](r[h(0x13d)](r['vNwPb'](C, 0xffff) * 0x85ebca6b, r[h(0x117)](r[h(0x134)](r[h(0x141)](C, 0x10), 0x85ebca6b), 0xffff) << 0x10), 0xffffffff),
C ^= r[h(0x13a)](C, 0xd),
C = r[h(0xfe)](r[h(0x118)](r[h(0x12d)](r[h(0x123)](C, 0xffff), 0xc2b2ae35), r['dLMKj'](r[h(0x13c)](r[h(0x121)](r['jHvVc'](C, 0x10), 0xc2b2ae35), 0xffff), 0x10)), 0xffffffff),
C ^= r[h(0x126)](C, 0x10),
result = r[h(0x104)](r[h(0x105)](r[h(0x157)](r[h(0x10d)](r[h(0x10d)](C >>> 0x0, '|'), j) + '|', f), '|'), N),
result;
}
function setCookie(M, B) {
var O = a
, j = {
'EyJtp': O(0x106),
'MeUzm': O(0x109),
'hZCEl': function(b, T) {
return b + T;
},
'vkRGS': function(b, T) {
return b + T;
},
'mTySG': function(b, T) {
return b(T);
},
'uOefP': function(b, T) {
return b == T;
},
'zlyUs': ';path=/',
'DHkIL': O(0xf8),
'vBwOt': function(b, T) {
return b + T;
},
'mGkxk': function(b, T) {
return b + T;
},
'pReXq': function(b, T) {
return b(T);
},
'wiGeS': function(b, T) {
return b + T;
},
'WHFvT': ';expires=',
'YNynO': function(b, T) {
return b + T;
},
'FLGyw': function(b, T) {
return b(T);
},
'ysIEr': function(b, T) {
return b + T;
},
'PHiYu': function(b, T) {
return b + T;
},
'VIwmN': function(b, T) {
return b(T);
},
'ubdGA': function(b, T) {
return b + T;
},
'RvZLO': O(0xf6)
}
, f = j[O(0x11a)][O(0x140)]('|')
, N = 0x0;
while (!![]) {
switch (f[N++]) {
case '0':
var r = j[O(0x149)];
continue;
case '1':
W[O(0x116)](j['hZCEl'](W[O(0x12f)](), B));
continue;
case '2':
var W = new Date();
continue;
case '3':
I ? (document[O(0x135)] = j['vkRGS'](j['vkRGS'](j[O(0x125)](j[O(0x102)](A, '=') + j[O(0x154)](escape, M), j[O(0x132)](B, null) ? '' : O(0x155) + W[O(0x11e)]()), j[O(0xfa)]), j[O(0x10e)]),
document[O(0x135)] = j['vBwOt'](j[O(0x125)](j[O(0x125)](j[O(0x14a)](r, '=') + j['pReXq'](escape, C), B == null ? '' : j['wiGeS'](j[O(0x136)], W[O(0x11e)]())), O(0x13b)), O(0xf8))) : (document[O(0x135)] = j[O(0x153)](j['hZCEl'](j['hZCEl'](A, '='), j[O(0xf7)](escape, M)) + (j[O(0x132)](B, null) ? '' : j[O(0x102)](O(0x155), W[O(0x11e)]())), j[O(0xfa)]),
document[O(0x135)] = j[O(0x114)](j[O(0x138)](j['PHiYu'](r, '='), j[O(0x127)](escape, C)) + (B == null ? '' : j[O(0x10c)](j[O(0x136)], W[O(0x11e)]())), j['zlyUs']));
continue;
case '4':
var I = O(0x103) === document[O(0x131)][O(0x13f)] ? !![] : ![];
continue;
case '5':
var A = O(0x11c);
continue;
case '6':
var C = j[O(0xff)];
continue;
}
break;
}
}
function a(M, B) {
var j = Z();
return a = function(f, N) {
f = f - 0xf4;
var r = j[f];
return r;
}
,
a(M, B);
}
function check() {
var R = a
, M = {
'VDyTo': R(0xf4),
'fzCyE': R(0x111),
'NRYtj': function(C, b, T) {
return C(b, T);
},
'dRcWF': 'parm_1',
'Fbuli': function(C, b, T, x, l, P, d) {
return C(b, T, x, l, P, d);
}
}
, B = M[R(0x113)][R(0x140)]('|')
, j = 0x0;
while (!![]) {
switch (B[j++]) {
case '0':
var f = document['documentElement'][R(0x148)];
continue;
case '1':
window['location'][R(0x110)](!![]);
continue;
case '2':
var N = document['documentElement'][R(0x128)];
continue;
case '3':
var r = document[R(0x150)](M[R(0x10a)])[R(0x10b)];
continue;
case '4':
console['log'](document['cookie']);
continue;
case '5':
console[R(0x152)](document[R(0x131)][R(0x13f)]);
continue;
case '6':
var W = window['location'][R(0x137)];
continue;
case '7':
M[R(0x144)](setCookie, A, 0x1);
continue;
case '8':
var I = document[R(0x150)](M[R(0x120)])[R(0x10b)];
continue;
case '9':
var A = M[R(0xfc)](hash32, W, r, I, f, N, I);
continue;
}
break;
}
}
script>
body>
html>