某乎x-zse-96加密算法分析与还原
文章目录
- 1. 写在前面
- 2. 接口分析
- 3. 加密分析
- 4. 算法实现
【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1. 写在前面
最近比较忙,有近一个月没更新文章了~在上次周末的时候刚好有一个小需求需对全网一些主流的平台做一个关键词扫描。其中某些平台的话以前的文章都有过分析,所以没有文章的就简单记录一下吧!
分析网站:
aHR0cHM6Ly93d3cuemhpaHUuY29tL3NlYXJjaD90eXBlPWNvbnRlbnQmcT0=
2. 接口分析
搜索接口的话除了x-zse-96
需要解决动态生成外,其他的几个可以不需要去管它,如下所示:
3. 加密分析
这里的话全局搜索及跟栈都可以找到加密参数生成的入口位置
可以看到上面tp
的话是一个拼接的长字符串,由四部分相加组成。请求头里面的X-Zse-93
、请求的接口路径、cookie
里面的d_c0
字段值、最后一个的开头3_2.0
特征很明显也是请求头内的X-Zse-81
参数,如下所示:
然后上面计算得到的MD5
值再经过tJ(ti).encrypt()
进行加密得到最终的64
位密文参数值,如下所示:
重点就是后续对MD5
二次加密的过程,需要去还原出来!这里作者当时为了快速实现需求也是做了一套补环境的方案!如果是补环境的话,那就会简单很多。把ed
方法拿出来,因为它是入口,再把那个涉及vmp
的1514
模块下面的JS全部拿下来并导出
然后在***.filter(Boolean).join("+")
这里拼接的地方拿到拼接的参数做一个标准的MD5
后再调用ZP
丢进行,D
是二段加密的方法入口处,tt
就是上面做了MD5
的值,如下所示:
然后剩下来的就是挂一个Poxy
开始对着来补环境了,如下所示:
这里的话就不去细说补环境了,网上公开的内容也蛮多,开始来分析纯算法的加密过程,核心的二段加密在1514
模块内是经过VMP
,所以需要去分析这段JS源码具体的加密逻辑实现的流程,如下所示:
1514: function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var _type_of = __webpack_require__(74185)
, x = function(tt) {
return C(tt) || s(tt) || t()
}
, C = function(tt) {
if (Array.isArray(tt)) {
for (var te = 0, tr = Array(tt.length); te < tt.length; te++)
tr[te] = tt[te];
return tr
}
}
, s = function(tt) {
if (Symbol.A in Object(tt) || "[object Arguments]" === Object.prototype.toString.call(tt))
return Array.from(tt)
}
, t = function() {
throw TypeError("Invalid attempt to spread non-iterable instance")
}
, i = function(tt, te, tr) {
te[tr] = 255 & tt >>> 24,
te[tr + 1] = 255 & tt >>> 16,
te[tr + 2] = 255 & tt >>> 8,
te[tr + 3] = 255 & tt
}
, B = function(tt, te) {
return (255 & tt[te]) << 24 | (255 & tt[te + 1]) << 16 | (255 & tt[te + 2]) << 8 | 255 & tt[te + 3]
}
, Q = function(tt, te) {
return (4294967295 & tt) << te | tt >>> 32 - te
}
, G = function(tt) {
var te = [, , , , ]
, tr = [, , , , ];
i(tt, te, 0),
tr[0] = h.zb[255 & te[0]],
tr[1] = h.zb[255 & te[1]],
tr[2] = h.zb[255 & te[2]],
tr[3] = h.zb[255 & te[3]];
var ti = B(tr, 0);
return ti ^ Q(ti, 2) ^ Q(ti, 10) ^ Q(ti, 18) ^ Q(ti, 24)
}
, l = function() {
this.C = [0, 0, 0, 0],
this.s = 0,
this.t = [],
this.S = [],
this.h = [],
this.i = [],
this.B = [],
this.Q = !1,
this.G = [],
this.D = [],
this.w = 1024,
this.g = null,
this.a = Date.now(),
this.e = 0,
this.T = 255,
this.V = null,
this.U = Date.now,
this.M = Array(32)
};
function o(tt) {
return (o = "function" == typeof Symbol && "symbol" == _type_of._(Symbol.A) ? function(tt) {
return void 0 === tt ? "undefined" : _type_of._(tt)
}
: function(tt) {
return tt && "function" == typeof Symbol && tt.constructor === Symbol && tt !== Symbol.prototype ? "symbol" : void 0 === tt ? "undefined" : _type_of._(tt)
}
)(tt)
}
__webpack_unused_export__ = {
value: !0
};
var __webpack_unused_export__, h, A = "3.0", S = "undefined" != typeof window ? window : {}, __g = {
x: function(tt, te) {
for (var tr = [], ti = tt.length, ta = 0; 0 < ti; ti -= 16) {
for (var tu = tt.slice(16 * ta, 16 * (ta + 1)), tc = Array(16), tf = 0; tf < 16; tf++)
tc[tf] = tu[tf] ^ te[tf];
te = __g.r(tc),
tr = tr.concat(te),
ta++
}
return tr
},
r: function(tt) {
var te = Array(16)
, tr = Array(36);
tr[0] = B(tt, 0),
tr[1] = B(tt, 4),
tr[2] = B(tt, 8),
tr[3] = B(tt, 12);
for (var ti = 0; ti < 32; ti++) {
var ta = G(tr[ti + 1] ^ tr[ti + 2] ^ tr[ti + 3] ^ h.zk[ti]);
tr[ti + 4] = tr[ti] ^ ta
}
return i(tr[35], te, 0),
i(tr[34], te, 4),
i(tr[33], te, 8),
i(tr[32], te, 12),
te
}
};
l.prototype.O = function(A, C, s) {
for (var t, S, h, i, B, Q, G, D, w, g, a, e, E, T, r, V, U, M, O, c, I; this.T < this.w; )
try {
switch (this.T) {
case 27:
this.C[this.c] = this.C[this.I] >> this.C[this.F],
this.M[12] = 35,
this.T = this.T * (this.C.length + (this.M[13] ? 3 : 9)) + 1;
break;
case 34:
this.C[this.c] = this.C[this.I] & this.C[this.F],
this.T = this.T * (this.M[15] - 6) + 12;
break;
case 41:
this.C[this.c] = this.C[this.I] <= this.C[this.F],
this.T = 8 * this.T + 27;
break;
case 48:
this.C[this.c] = !this.C[this.I],
this.T = 7 * this.T + 16;
break;
case 50:
this.C[this.c] = this.C[this.I] | this.C[this.F],
this.T = 6 * this.T + 52;
break;
case 57:
this.C[this.c] = this.C[this.I] >>> this.C[this.F],
this.T = 7 * this.T - 47;
break;
case 64:
this.C[this.c] = this.C[this.I] << this.C[this.F],
this.T = 5 * this.T + 32;
break;
case 71:
this.C[this.c] = this.C[this.I] ^ this.C[this.F],
this.T = 6 * this.T - 74;
break;
case 78:
this.C[this.c] = this.C[this.I] & this.C[this.F],
this.T = 4 * this.T + 40;
break;
case 80:
this.C[this.c] = this.C[this.I] < this.C[this.F],
this.T = 5 * this.T - 48;
break;
case 87:
this.C[this.c] = -this.C[this.I],
this.T = 3 * this.T + 91;
break;
case 94:
this.C[this.c] = this.C[this.I] > this.C[this.F],
this.T = 4 * this.T - 24;
break;
case 101:
this.C[this.c] = this.C[this.I]in this.C[this.F],
this.T = 3 * this.T + 49;
break;
case 108:
this.C[this.c] = o(this.C[this.I]),
this.T = 2 * this.T + 136;
break;
case 110:
this.C[this.c] = this.C[this.I] !== this.C[this.F],
this.T += 242;
break;
case 117:
this.C[this.c] = this.C[this.I] && this.C[this.F],
this.T = 3 * this.T + 1;
break;
case 124:
this.C[this.c] = this.C[this.I] || this.C[this.F],
this.T += 228;
break;
case 131:
this.C[this.c] = this.C[this.I] >= this.C[this.F],
this.T = 3 * this.T - 41;
break;
case 138:
this.C[this.c] = this.C[this.I] == this.C[this.F],
this.T = 2 * this.T + 76;
break;
case 140:
this.C[this.c] = this.C[this.I] % this.C[this.F],
this.T += 212;
break;
case 147:
this.C[this.c] = this.C[this.I] / this.C[this.F],
this.T += 205;
break;
case 154:
this.C[this.c] = this.C[this.I] * this.C[this.F],
this.T += 198;
break;
case 161:
this.C[this.c] = this.C[this.I] - this.C[this.F],
this.T += 191;
break;
case 168:
this.C[this.c] = this.C[this.I] + this.C[this.F],
this.T = 2 * this.T + 16;
break;
case 254:
this.C[this.c] = eval(i),
this.T += 20 < this.M[11] ? 98 : 89;
break;
case 255:
this.s = C || 0,
this.M[26] = 52,
this.T += this.M[13] ? 8 : 6;
break;
case 258:
g = {};
for (var F = 0; F < this.k; F++)
e = this.i.pop(),
a = this.i.pop(),
g[a] = e;
this.C[this.W] = g,
this.T += 94;
break;
case 261:
this.D = s || [],
this.M[11] = 68,
this.T += this.M[26] ? 3 : 5;
break;
case 264:
this.M[15] = 16,
this.T = "string" == typeof A ? 331 : 336;
break;
case 266:
this.C[this.I][i] = this.i.pop(),
this.T += 86;
break;
case 278:
this.C[this.c] = this.C[this.I][i],
this.T += this.M[22] ? 63 : 74;
break;
case 283:
this.C[this.c] = eval(String.fromCharCode(this.C[this.I]));
break;
case 300:
S = this.U(),
this.M[0] = 66,
this.T += this.M[11];
break;
case 331:
D = atob(A),
w = D.charCodeAt(0) << 16 | D.charCodeAt(1) << 8 | D.charCodeAt(2);
for (var k = 3; k < w + 3; k += 3)
this.G.push(D.charCodeAt(k) << 16 | D.charCodeAt(k + 1) << 8 | D.charCodeAt(k + 2));
for (V = w + 3; V < D.length; )
E = D.charCodeAt(V) << 8 | D.charCodeAt(V + 1),
T = D.slice(V + 2, V + 2 + E),
this.D.push(T),
V += E + 2;
this.M[21] = 8,
this.T += 1e3 < V ? 21 : 35;
break;
case 336:
this.G = A,
this.D = s,
this.M[18] = 134,
this.T += this.M[15];
break;
case 344:
this.T = 3 * this.T - 8;
break;
case 350:
U = 66,
M = [],
I = this.D[this.k];
for (var W = 0; W < I.length; W++)
M.push(String.fromCharCode(24 ^ I.charCodeAt(W) ^ U)),
U = 24 ^ I.charCodeAt(W) ^ U;
r = parseInt(M.join("").split("|")[1]),
this.C[this.W] = this.i.slice(this.i.length - r),
this.i = this.i.slice(0, this.i.length - r),
this.T += 2;
break;
case 352:
this.e = this.G[this.s++],
this.T -= this.M[26];
break;
case 360:
this.a = S,
this.T += this.M[0];
break;
case 368:
this.T -= 500 < S - this.a ? 24 : 8;
break;
case 380:
this.i.push(16383 & this.e),
this.T -= 28;
break;
case 400:
this.i.push(this.S[16383 & this.e]),
this.T -= 48;
break;
case 408:
this.T -= 64;
break;
case 413:
this.C[this.e >> 15 & 7] = (this.e >> 18 & 1) == 0 ? 32767 & this.e : this.S[32767 & this.e],
this.T -= 61;
break;
case 418:
this.S[65535 & this.e] = this.C[this.e >> 16 & 7],
this.T -= this.e >> 16 < 20 ? 66 : 80;
break;
case 423:
this.c = this.e >> 16 & 7,
this.I = this.e >> 13 & 7,
this.F = this.e >> 10 & 7,
this.J = 1023 & this.e,
this.T -= 255 + 6 * this.J + this.J % 5;
break;
case 426:
this.T += 5 * (this.e >> 19) - 18;
break;
case 428:
this.W = this.e >> 16 & 7,
this.k = 65535 & this.e,
this.t.push(this.s),
this.h.push(this.S),
this.s = this.C[this.W],
this.S = [];
for (var J = 0; J < this.k; J++)
this.S.unshift(this.i.pop());
this.B.push(this.i),
this.i = [],
this.T -= 76;
break;
case 433:
this.s = this.t.pop(),
this.S = this.h.pop(),
this.i = this.B.pop(),
this.T -= 81;
break;
case 438:
this.Q = this.C[this.e >> 16 & 7],
this.T -= 86;
break;
case 440:
U = 66,
M = [],
I = this.D[16383 & this.e];
for (var b = 0; b < I.length; b++)
M.push(String.fromCharCode(24 ^ I.charCodeAt(b) ^ U)),
U = 24 ^ I.charCodeAt(b) ^ U;
M = M.join("").split("|"),
O = parseInt(M.shift()),
this.i.push(0 === O ? M.join("|") : 1 === O ? -1 !== M.join().indexOf(".") ? parseInt(M.join()) : parseFloat(M.join()) : 2 === O ? eval(M.join()) : 3 === O ? null : void 0),
this.T -= 88;
break;
case 443:
this.b = this.e >> 2 & 65535,
this.J = 3 & this.e,
0 === this.J ? this.s = this.b : 1 === this.J ? this.Q && (this.s = this.b) : 2 === this.J && this.Q || (this.s = this.b),
this.g = null,
this.T -= 91;
break;
case 445:
this.i.push(this.C[this.e >> 14 & 7]),
this.T -= 93;
break;
case 448:
this.W = this.e >> 16 & 7,
this.k = this.e >> 2 & 4095,
this.J = 3 & this.e,
Q = 1 === this.J && this.i.pop(),
G = this.i.slice(this.i.length - this.k, this.i.length),
this.i = this.i.slice(0, this.i.length - this.k),
c = 2 < G.length ? 3 : G.length,
this.T += 6 * this.J + 1 + 10 * c;
break;
case 449:
this.C[3] = this.C[this.W](),
this.T -= 97 - G.length;
break;
case 455:
this.C[3] = this.C[this.W][Q](),
this.T -= 103 + G.length;
break;
case 453:
B = this.e >> 17 & 3,
this.T = 0 === B ? 445 : 1 === B ? 380 : 2 === B ? 400 : 440;
break;
case 458:
this.J = this.e >> 17 & 3,
this.c = this.e >> 14 & 7,
this.I = this.e >> 11 & 7,
i = this.i.pop(),
this.T -= 12 * this.J + 180;
break;
case 459:
this.C[3] = this.C[this.W](G[0]),
this.T -= 100 + 7 * G.length;
break;
case 461:
this.C[3] = new this.C[this.W],
this.T -= 109 - G.length;
break;
case 463:
U = 66,
M = [],
I = this.D[65535 & this.e];
for (var n = 0; n < I.length; n++)
M.push(String.fromCharCode(24 ^ I.charCodeAt(n) ^ U)),
U = 24 ^ I.charCodeAt(n) ^ U;
M = M.join("").split("|"),
O = parseInt(M.shift()),
this.T += 10 * O + 3;
break;
case 465:
this.C[3] = this.C[this.W][Q](G[0]),
this.T -= 13 * G.length + 100;
break;
case 466:
this.C[this.e >> 16 & 7] = M.join("|"),
this.T -= 114 * M.length;
break;
case 468:
this.g = 65535 & this.e,
this.T -= 116;
break;
case 469:
this.C[3] = this.C[this.W](G[0], G[1]),
this.T -= 119 - G.length;
break;
case 471:
this.C[3] = new this.C[this.W](G[0]),
this.T -= 118 + G.length;
break;
case 473:
throw this.C[this.e >> 16 & 7];
case 475:
this.C[3] = this.C[this.W][Q](G[0], G[1]),
this.T -= 123;
break;
case 476:
this.C[this.e >> 16 & 7] = -1 !== M.join().indexOf(".") ? parseInt(M.join()) : parseFloat(M.join()),
this.T -= this.M[21] < 10 ? 124 : 126;
break;
case 478:
t = [0].concat(x(this.S)),
this.V = 65535 & this.e,
h = this,
this.C[3] = function(tt) {
var te = new l;
return te.S = t,
te.S[0] = tt,
te.O(h.G, h.V, h.D),
te.C[3]
}
,
this.T -= 50 < this.M[3] ? 120 : 126;
break;
case 479:
this.C[3] = this.C[this.W].apply(null, G),
this.M[3] = 168,
this.T -= this.M[9] ? 127 : 128;
break;
case 481:
this.C[3] = new this.C[this.W](G[0],G[1]),
this.T -= 10 * G.length + 109;
break;
case 483:
this.J = this.e >> 15 & 15,
this.W = this.e >> 12 & 7,
this.k = 4095 & this.e,
this.T = 0 === this.J ? 258 : 350;
break;
case 485:
this.C[3] = this.C[this.W][Q].apply(null, G),
this.T -= this.M[15] % 2 == 1 ? 143 : 133;
break;
case 486:
this.C[this.e >> 16 & 7] = eval(M.join()),
this.T -= this.M[18];
break;
case 491:
this.C[3] = new this.C[this.W].apply(null,G),
this.T -= this.M[8] / this.M[1] < 10 ? 139 : 130;
break;
case 496:
this.C[this.e >> 16 & 7] = null,
this.T -= 10 < this.M[5] - this.M[3] ? 160 : 144;
break;
case 506:
this.C[this.e >> 16 & 7] = void 0,
this.T -= this.M[18] % this.M[12] == 1 ? 154 : 145;
break;
default:
this.T = this.w
}
} catch (A) {
this.g && (this.s = this.g),
this.T -= 114
}
}
,
"undefined" != typeof window && (S.__ZH__ = S.__ZH__ || {},
h = S.__ZH__.zse = S.__ZH__.zse || {},
(new l).O("ABt7CAAUSAAACADfSAAACAD1SAAACAAHSAAACAD4SAAACAACSAAACADCSAAACADRSAAACABXSAAACAAGSAAACADjSAAACAD9SAAACADwSAAACACASAAACADeSAAACABbSAAACADtSAAACAAJSAAACAB9SAAACACdSAAACADmSAAACABdSAAACAD8SAAACADNSAAACABaSAAACABPSAAACACQSAAACADHSAAACACfSAAACADFSAAACAC6SAAACACnSAAACAAnSAAACAAlSAAACACcSAAACADGSAAACAAmSAAACAAqSAAACAArSAAACACoSAAACADZSAAACACZSAAACAAPSAAACABnSAAACABQSAAACAC9SAAACABHSAAACAC/SAAACABhSAAACABUSAAACAD3SAAACABfSAAACAAkSAAACABFSAAACAAOSAAACAAjSAAACAAMSAAACACrSAAACAAcSAAACABySAAACACySAAACACUSAAACABWSAAACAC2SAAACAAgSAAACABTSAAACACeSAAACABtSAAACAAWSAAACAD/SAAACABeSAAACADuSAAACACXSAAACABVSAAACABNSAAACAB8SAAACAD+SAAACAASSAAACAAESAAACAAaSAAACAB7SAAACACwSAAACADoSAAACADBSAAACACDSAAACACsSAAACACPSAAACACOSAAACACWSAAACAAeSAAACAAKSAAACACSSAAACACiSAAACAA+SAAACADgSAAACADaSAAACADESAAACADlSAAACAABSAAACADASAAACADVSAAACAAbSAAACABuSAAACAA4SAAACADnSAAACAC0SAAACACKSAAACABrSAAACADySAAACAC7SAAACAA2SAAACAB4SAAACAATSAAACAAsSAAACAB1SAAACADkSAAACADXSAAACADLSAAACAA1SAAACADvSAAACAD7SAAACAB/SAAACABRSAAACAALSAAACACFSAAACABgSAAACADMSAAACACESAAACAApSAAACABzSAAACABJSAAACAA3SAAACAD5SAAACACTSAAACABmSAAACAAwSAAACAB6SAAACACRSAAACABqSAAACAB2SAAACABKSAAACAC+SAAACAAdSAAACAAQSAAACACuSAAACAAFSAAACACxSAAACACBSAAACAA/SAAACABxSAAACABjSAAACAAfSAAACAChSAAACABMSAAACAD2SAAACAAiSAAACADTSAAACAANSAAACAA8SAAACABESAAACADPSAAACACgSAAACABBSAAACABvSAAACABSSAAACAClSAAACABDSAAACACpSAAACADhSAAACAA5SAAACABwSAAACAD0SAAACACbSAAACAAzSAAACADsSAAACADISAAACADpSAAACAA6SAAACAA9SAAACAAvSAAACABkSAAACACJSAAACAC5SAAACABASAAACAARSAAACABGSAAACADqSAAACACjSAAACADbSAAACABsSAAACACqSAAACACmSAAACAA7SAAACACVSAAACAA0SAAACABpSAAACAAYSAAACADUSAAACABOSAAACACtSAAACAAtSAAACAAASAAACAB0SAAACADiSAAACAB3SAAACACISAAACADOSAAACACHSAAACACvSAAACADDSAAACAAZSAAACABcSAAACAB5SAAACADQSAAACAB+SAAACACLSAAACAADSAAACABLSAAACACNSAAACAAVSAAACACCSAAACABiSAAACADxSAAACAAoSAAACACaSAAACABCSAAACAC4SAAACAAxSAAACAC1SAAACAAuSAAACADzSAAACABYSAAACABlSAAACAC3SAAACAAISAAACAAXSAAACABISAAACAC8SAAACABoSAAACACzSAAACADSSAAACACGSAAACAD6SAAACADJSAAACACkSAAACABZSAAACADYSAAACADKSAAACADcSAAACAAySAAACADdSAAACACYSAAACACMSAAACAAhSAAACADrSAAACADWSAAAeIAAEAAACAB4SAAACAAySAAACABiSAAACABlSAAACABjSAAACABiSAAACAB3SAAACABkSAAACABnSAAACABrSAAACABjSAAACAB3SAAACABhSAAACABjSAAACABuSAAACABvSAAAeIABEAABCABkSAAACAAzSAAACABkSAAACAAySAAACABlSAAACAA3SAAACAAySAAACAA2SAAACABmSAAACAA1SAAACAAwSAAACABkSAAACAA0SAAACAAxSAAACAAwSAAACAAxSAAAeIABEAACCAAgSAAATgACVAAAQAAGEwADDAADSAAADAACSAAADAAASAAACANcIAADDAADSAAASAAATgADVAAATgAEUAAATgAFUAAATgAGUgAADAAASAAASAAATgADVAAATgAEUAAATgAFUAAATgAHUgAADAABSAAASAAATgADVAAATgAEUAAATgAFUAAATgAIUgAAcAgUSMAATgAJVAAATgAKUgAAAAAADAABSAAADAAAUAAACID/GwQPCAAYG2AREwAGDAABCIABGwQASMAADAAAUAAACID/GwQPCAAQG2AREwAHDAABCIACGwQASMAADAAAUAAACID/GwQPCAAIG2AREwAIDAABCIADGwQASMAADAAAUAAACID/GwQPEwAJDYAGDAAHG2ATDAAIG2ATDAAJG2ATKAAACAD/DIAACQAYGygSGwwPSMAASMAADAACSAAADAABUgAACAD/DIAACQAQGygSGwwPSMAASMAADAACCIABGwQASMAADAABUgAACAD/DIAACQAIGygSGwwPSMAASMAADAACCIACGwQASMAADAABUgAACAD/DIAAGwQPSMAASMAADAACCIADGwQASMAADAABUgAAKAAACAAgDIABGwQBEwANDAAAWQALGwQPDAABG2AREwAODAAODIAADQANGygSGwwTEwAPDYAPKAAACAAESAAATgACVAAAQAAGEwAQCAAESAAATgACVAAAQAAGEwAFDAAASAAADAAQSAAACAAASAAACAKsIAADCAAASAAADAAQUAAACID/GwQPSMAADAABUAAASAAASAAACAAASAAADAAFUgAACAABSAAADAAQUAAACID/GwQPSMAADAABUAAASAAASAAACAABSAAADAAFUgAACAACSAAADAAQUAAACID/GwQPSMAADAABUAAASAAASAAACAACSAAADAAFUgAACAADSAAADAAQUAAACID/GwQPSMAADAABUAAASAAASAAACAADSAAADAAFUgAADAAFSAAACAAASAAACAJ8IAACEwARDAARSAAACAANSAAACALdIAACEwASDAARSAAACAAXSAAACALdIAACEwATDAARDIASGwQQDAATG2AQEwAUDYAUKAAAWAAMSAAAWAANSAAAWAAOSAAAWAAPSAAAWAAQSAAAWAARSAAAWAASSAAAWAATSAAAWAAUSAAAWAAVSAAAWAAWSAAAWAAXSAAAWAAYSAAAWAAZSAAAWAAaSAAAWAAbSAAAWAAcSAAAWAAdSAAAWAAeSAAAWAAfSAAAWAAgSAAAWAAhSAAAWAAiSAAAWAAjSAAAWAAkSAAAWAAlSAAAWAAmSAAAWAAnSAAAWAAoSAAAWAApSAAAWAAqSAAAWAArSAAAeIAsEAAXWAAtSAAAWAAuSAAAWAAvSAAAWAAwSAAAeIAxEAAYCAAESAAATgACVAAAQAAGEwAZCAAkSAAATgACVAAAQAAGEwAaDAABSAAACAAASAAACAJ8IAACSMAASMAACAAASAAADAAZUgAADAABSAAACAAESAAACAJ8IAACSMAASMAACAABSAAADAAZUgAADAABSAAACAAISAAACAJ8IAACSMAASMAACAACSAAADAAZUgAADAABSAAACAAMSAAACAJ8IAACSMAASMAACAADSAAADAAZUgAACAAASAAADAAZUAAACIAASEAADIAYUEgAGwQQSMAASMAACAAASAAADAAaUgAACAABSAAADAAZUAAACIABSEAADIAYUEgAGwQQSMAASMAACAABSAAADAAaUgAACAACSAAADAAZUAAACIACSEAADIAYUEgAGwQQSMAASMAACAACSAAADAAaUgAACAADSAAADAAZUAAACIADSEAADIAYUEgAGwQQSMAASMAACAADSAAADAAaUgAACAAAEAAJDAAJCIAgGwQOMwAGOBG2DAAJCIABGwQASMAADAAaUAAAEAAbDAAJCIACGwQASMAADAAaUAAAEAAcDAAJCIADGwQASMAADAAaUAAAEAAdDAAbDIAcGwQQDAAdG2AQDAAJSAAADAAXUAAAG2AQEwAeDAAeSAAADAACSAAACALvIAACEwAfDAAJSAAADAAaUAAADIAfGwQQSMAASMAADAAJCIAEGwQASMAADAAaUgAADAAJCIAEGwQASMAADAAaUAAASAAASAAADAAJSAAADAAAUgAADAAJCIABGQQAEQAJOBCIKAAADAABTgAyUAAACIAQGwQEEwAVCAAQDIAVGwQBEwAKCAAAEAAhDAAhDIAKGwQOMwAGOBImDAAKSAAADAABTgAzQAAFDAAhCIABGQQAEQAhOBHoCAAASAAACAAQSAAADAABTgA0QAAJEwAiCAAQSAAATgACVAAAQAAGEwAjCAAAEAALDAALCIAQGwQOMwAGOBLSDAALSAAADAAiUAAADIALSEAADIAAUEgAGwQQCAAqG2AQSMAASMAADAALSAAADAAjUgAA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"));
var D = function(tt) {
return __g._encrypt(encodeURIComponent(tt))
};
exports.XL = A,
exports.ZP = D
},
开始之前可以先静态去分析一下上面的这段JS,先是一个switch
然后通过this.T
的值来决定执行啥操作!它相当于一个状态的变量
,不同的case
分支来对应不同的操作,VMP
常见的一个实现方式
然后往下翻翻,一堆位运算
以此来增加代码的复杂性
跟混淆度
。代码里面的那个eval
的函数,也是常见的一个特征之一!来动态执行一些JS
代码,增强隐蔽性,如下所示:
开始对case
的分支中关键操作位置插桩日志(如赋值、函数调用、位运算
)以及相关变量的值。
开始分析日志,首先看不到第一步MD5
计算出来的结果进行一个charCodeAt
操作转换为32
位的一个数组。实现如下所示:
md5_value = 'MD5的值'
array_32 = [ord(i) for i in md5_value]
然后第二步在32
位的数组基础上再次往首插入两个数值,0
是可以直接固定的,另一个107
是随机数取整得到的,如下所示:
之后第三步的时候它这个MD5
的数组最终会填充到48
位,从上面首位插两位数值以后就是往末位继续插值,不断的往末端追加14
,直到满足48
位数组为止,如下所示:
接着第四步继续往下上面得到一个头尾填充后的48
位数组以后,再次通过分片的方式对48
位数组取[:16]
的方式得到一个新的16
位数组,如下所示:
至此,来到了第五步!上面截止到当前已经有了三个数组
。继续往下还是一些数组的操作。这种时候边分析边记录一些关键点很有必要,不然梳理起来有点容易丢失上下文~
先将上面分片
得到的16
位数组作为参数传递到某个自定义的函数内,这个函数主要实现的就是对这个16
位数进行加密处理的,函数内一个固定的长度为16
的数组,作为偏移量用于后续的按位异或操作生成16
数组,如下所示:
它那个调用的函数是它自己内部自定义的函数,代码如下所示:
16
位第一轮数组将经过上面的算法进行运算。过程则是将输入的16
位字节数组拆分成4
个32
位整数并存储到临时数组的前4
个位置!然后进行32
次循环,每次循环进行一系列的变换操作,然后需要注意一下的就是在循环的过程中h.zk
是一个预先定义好的常量数组!将从里面索引元素进行按位异或操作!对照上面的日志JS还原大致就是下面这样子的:
ENCRYPT_CONSTANTS = {
"zk": [], # 自行获取
"zb": [] # 自行获取
}
def split_int_to_bytes(int_value, byte_array, start_index):
byte_array[start_index] = (int_value >> 24) & 255
byte_array[start_index + 1] = (int_value >> 16) & 255
byte_array[start_index + 2] = (int_value >> 8) & 255
byte_array[start_index + 3] = int_value & 255
return byte_array
def circular_left_shift(int_value, shift_amount):
int_value = int_value & 0xFFFFFFFF
return ((int_value << shift_amount) | (int_value >> (32 - shift_amount))) & 0xFFFFFFFF
def combine_bytes_to_int(byte_array, start_index):
return ((byte_array[start_index] & 255) << 24) | ((byte_array[start_index + 1] & 255) << 16) | ((byte_array[start_index + 2] & 255) << 8) | (byte_array[start_index + 3] & 255)
def transform_32bit_int(int_value):
byte_array_1 = [0] * 4
byte_array_2 = [0] * 4
byte_array_1 = split_int_to_bytes(int_value, byte_array_1, 0)
byte_array_2[0] = ENCRYPT_CONSTANTS["zb"][byte_array_1[0] & 255]
byte_array_2[1] = ENCRYPT_CONSTANTS["zb"][byte_array_1[1] & 255]
byte_array_2[2] = ENCRYPT_CONSTANTS["zb"][byte_array_1[2] & 255]
byte_array_2[3] = ENCRYPT_CONSTANTS["zb"][byte_array_1[3] & 255]
combined_int = combine_bytes_to_int(byte_array_2, 0)
return combined_int ^ circular_left_shift(combined_int, 2) ^ circular_left_shift(combined_int, 10) ^ circular_left_shift(combined_int, 18) ^ circular_left_shift(combined_int, 24)
def transform_16_byte_array(byte_array):
result_array = [0] * 16
temp_array = [0] * 36
temp_array[0] = combine_bytes_to_int(byte_array, 0)
temp_array[1] = combine_bytes_to_int(byte_array, 4)
temp_array[2] = combine_bytes_to_int(byte_array, 8)
temp_array[3] = combine_bytes_to_int(byte_array, 12)
for i in range(32):
transformed_value = transform_32bit_int(temp_array[i + 1] ^ temp_array[i + 2] ^ temp_array[i + 3] ^ ENCRYPT_CONSTANTS["zk"][i])
temp_array[i + 4] = temp_array[i] ^ transformed_value
result_array = split_int_to_bytes(temp_array[35], result_array, 0)
result_array = split_int_to_bytes(temp_array[34], result_array, 4)
result_array = split_int_to_bytes(temp_array[33], result_array, 8)
result_array = split_int_to_bytes(temp_array[32], result_array, 12)
return result_array
上面还原的Py
代码中的zk
32位数组与zb
256位定义数组可以自行通过日志信息拿到贴进去就可以,如下所示:
然后再来到第六步…第一次在上面对48
位数组取了一个[:16]
的分片数组,这里继续取[16:48]
剩余的数组部分,如下所示:
取了之后干什么?准备开始进行第七步!将上面第五步计算得到的新的16
位数组跟第六步的分片32
位数组进行运算。先是对32
位数组进行分组处理,按照16
字节一组来拆分出来。然后拆出来的每组跟传进来的那个16
数组进行异或!完了丢给第五步的那个算法得到一个32
位数组,最终16+32
得到一个48
数组,如下所示:
最后第八步将上面得到的48
位数组经过函数拆成3
个一组进行编码处理,三合一
为整数,然后将该整数按每6
位一组进行拆分,得到一个长度4
的数组,如下所示:
综上分析,这里可以用Py
进行算法操作的还原,代码实现如下:
def generate_initial_array(md5_hash):
initial_array = [ord(c) for c in md5_hash]
initial_array.insert(0, 0)
initial_array.insert(0, random.randint(0, 126))
while len(initial_array) < 48:
initial_array.append(14)
first_16_bytes = encrypt_16_byte_array(initial_array[:16])
remaining_32_bytes = process_32_byte_array(initial_array[16:48], first_16_bytes)
result_array = first_16_bytes + remaining_32_bytes
return result_array
最终就是遍历新得到的数组!将其作为索引从下面的固定的字符集里面不断的取对应值,生成一个64
位的密文结果,如下所示:
4. 算法实现
最后,某些常量数组以及字符集自己照着复现的时候补全就行,还原后的加密算法如下所示:
import hashlib
import random
ENCODE_CHAR_SET = "" # 自行获取
# 自行获取
ENCRYPT_CONSTANTS = {
"keys": [],
"arr": []
}
def split_int_to_bytes(int_value, byte_array, start_index):
byte_array[start_index] = (int_value >> 24) & 255
byte_array[start_index + 1] = (int_value >> 16) & 255
byte_array[start_index + 2] = (int_value >> 8) & 255
byte_array[start_index + 3] = int_value & 255
return byte_array
def circular_left_shift(int_value, shift_amount):
int_value = int_value & 0xFFFFFFFF
return ((int_value << shift_amount) | (int_value >> (32 - shift_amount))) & 0xFFFFFFFF
def combine_bytes_to_int(byte_array, start_index):
return ((byte_array[start_index] & 255) << 24) | ((byte_array[start_index + 1] & 255) << 16) | ((byte_array[start_index + 2] & 255) << 8) | (byte_array[start_index + 3] & 255)
def transform_32bit_int(int_value):
byte_array_1 = [0] * 4
byte_array_2 = [0] * 4
byte_array_1 = split_int_to_bytes(int_value, byte_array_1, 0)
byte_array_2[0] = ENCRYPT_CONSTANTS["arr"][byte_array_1[0] & 255]
byte_array_2[1] = ENCRYPT_CONSTANTS["arr"][byte_array_1[1] & 255]
byte_array_2[2] = ENCRYPT_CONSTANTS["arr"][byte_array_1[2] & 255]
byte_array_2[3] = ENCRYPT_CONSTANTS["arr"][byte_array_1[3] & 255]
combined_int = combine_bytes_to_int(byte_array_2, 0)
return combined_int ^ circular_left_shift(combined_int, 2) ^ circular_left_shift(combined_int, 10) ^ circular_left_shift(combined_int, 18) ^ circular_left_shift(combined_int, 24)
def transform_16_byte_array(byte_array):
result_array = [0] * 16
temp_array = [0] * 36
temp_array[0] = combine_bytes_to_int(byte_array, 0)
temp_array[1] = combine_bytes_to_int(byte_array, 4)
temp_array[2] = combine_bytes_to_int(byte_array, 8)
temp_array[3] = combine_bytes_to_int(byte_array, 12)
for i in range(32):
transformed_value = transform_32bit_int(temp_array[i + 1] ^ temp_array[i + 2] ^ temp_array[i + 3] ^ ENCRYPT_CONSTANTS["keys"][i])
temp_array[i + 4] = temp_array[i] ^ transformed_value
result_array = split_int_to_bytes(temp_array[35], result_array, 0)
result_array = split_int_to_bytes(temp_array[34], result_array, 4)
result_array = split_int_to_bytes(temp_array[33], result_array, 8)
result_array = split_int_to_bytes(temp_array[32], result_array, 12)
return result_array
def process_32_byte_array(byte_array, initial_array):
result_array = []
current_index = 0
remaining_length = len(byte_array)
while remaining_length > 0:
sub_array = byte_array[16 * current_index:16 * (current_index + 1)]
xor_array = [0] * 16
for i in range(16):
xor_array[i] = sub_array[i] ^ initial_array[i]
initial_array = transform_16_byte_array(xor_array)
result_array.extend(initial_array)
current_index += 1
remaining_length -= 16
return result_array
def encrypt_16_byte_array(byte_array):
result = []
offset_array = [] # 16位数组自行获取
for i in range(len(byte_array)):
xor_value_1 = byte_array[i] ^ offset_array[i]
xor_value_2 = xor_value_1 ^ 42
result.append(xor_value_2)
return transform_16_byte_array(result)
def encode_3_element_array(array):
shifted_value_1 = array[1] << 8
combined_value_1 = array[0] | shifted_value_1
shifted_value_2 = array[2] << 16
combined_value_2 = combined_value_1 | shifted_value_2
result_array = []
shift_amount = 6
result_array.append(combined_value_2 & 63)
while len(result_array) < 4:
shifted_value = combined_value_2 >> shift_amount
result_array.append(shifted_value & 63)
shift_amount += 6
return result_array
def generate_initial_array(md5_hash):
"""
根据 MD5 哈希值生成初始化数组
"""
initial_array = [ord(c) for c in md5_hash]
initial_array.insert(0, 0)
initial_array.insert(0, random.randint(0, 126))
while len(initial_array) < 48:
initial_array.append(14)
first_16_bytes = encrypt_16_byte_array(initial_array[:16])
remaining_32_bytes = process_32_byte_array(initial_array[16:48], first_16_bytes)
result_array = first_16_bytes + remaining_32_bytes
return result_array
def generate_zse_96_signature(md5_hash):
"""
根据 MD5 哈希值生成zse签名
"""
result_array = []
initial_array = generate_initial_array(md5_hash)
for i in range(47, -1, -4):
initial_array[i] ^= 58
initial_array.reverse()
for j in range(3, len(initial_array) + 1, 3):
sub_array = initial_array[j - 3:j]
result_array.extend(encode_3_element_array(sub_array))
signature = ""
for index in result_array:
signature += ENCODE_CHAR_SET[index]
return signature
最后,将Py
算法对接到搜索测试是通过的,验证结果如下所示: