前言
现在一些网站对 JavaScript 代码采取了一定的保护措施,比如变量名混淆、执行逻辑混淆、反调试、核心逻辑加密等,有的还对数据接口进行了加密,这次案例是通过补环境过 jsvmp。
声明
本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除!
案例分析
目标网址:
aHR0cHM6Ly93d3cuemhpaHUuY29tLw==
数据接口:
L2FwaS92NC9zZWFyY2hfdjM/Z2tfdmVyc2lvbj1nei1nYW9rYW8mdD1nZW5lcmFsJnE9
以上均做了脱敏处理,Base64 编码及解码方式:
import base64
# 编码
# result = base64.b64encode('待编码字符串'.encode('utf-8'))
# 解码
result = base64.b64decode('待解码字符串'.encode('utf-8'))
print(result)
常规 JavaScript 逆向思路
一般情况下,JavaScript 逆向分为三步:
- 寻找入口:逆向在大部分情况下就是找一些加密参数到底是怎么来的,关键逻辑可能写在某个关键的方法或者隐藏在某个关键的变量里,一个网站可能加载了很多 JavaScript 文件,如何从这么多的 JavaScript 文件的代码行中找到关键的位置,很重要;
- 调试分析:找到入口后,我们定位到某个参数可能是在某个方法中执行的了,那么里面的逻辑是怎么样的,调用了多少加密算法,经过了多少赋值变换,需要把整体思路整理清楚,以便于断点或反混淆工具等进行调试分析;
- 模拟执行:经过调试分析后,差不多弄清了逻辑,就需要对加密过程进行逻辑复现,以拿到最后我们想要的数据
接下来开始正式进行案例分析:
寻找入口
打开开发者人员工具,在搜索框中输入内容,点击搜索进行抓包,可以看到数据接口为 search_v3?gk_version=XXX&t=XXX:
请求头中有一些加密参数,经调试底下框中的这三个是必须携带的,之前版本知乎的搜索接口中是没有 x-zst-81 参数的,现在不仅加上了,还需要与 x-zse-96 参数相匹配,即两个参数必须是同一次请求生成的,不然就算两个参数值都是正确的也获取不到数据:
逆向分析
文章是之前写的,行号可能已经发生改变,不过位置及内容大差不差:
这两个参数的值直接拿着用也是可以获取到数据的,但是有时效性,所以还是需要对其进行逆向分析,看看究竟是如何生成的,先从 x-zse-96 开始,直接 ctrl + shift + f 全局搜索 x-zse-96 参数,会发现只有一个匹配结果:
进去后点击左下角 { } 格式化一下该 js 文件,再 ctrl + f 局部搜索一下 x-zse-96 参数,有两个匹配结果,在第 12690 行打下断点调试分析:
点击搜索,即会在此处断下,第 12690 行的 _ 为 x-zse-96 参数的值,第 12688 行的 m 为 x-zst-81 参数的值:
这里先跟进 x-zse-96 参数,_ 定义在第 12682 行,取了 T 函数中 signature 得值,signature 定义在第 12678 行:
(0, F(r).encrypt)(f()(s))
f()(s) 值为 32 位的字符串,经过 F(r).encrypt 加密得到了 x-zse-96 参数的值,s 定义在第 12675 行,是由几个字符串通过 + 拼接而成:
- i: 参数 x-zse-93 的值
- o:cookie 中的参数 dc0 的值
- u:接口 URL
- a:参数 x-zst-81 的值
- filter(Boolean):Boolean 遍历数组中的元素判断真假类型,返回 true 或者 false,filter(Boolean) 则为移除数组中返回值为 false 的元素
- join("+"):通过 + 进行拼接
接下来鼠标选中 f(),跟进去:
会跳转到第 21801 行,在第 21802 行打下断点调试,一直下一步断到搜索接口的位置:
- e:x-zse-93 的值 + 接口 URL + "dc0 的值"(双引号别掉了)+ x_zst_81 参数的值
- t、n:undefined
return 处是个三目表达式,由于 t 和 n 是 undefined,所以返回值结果为 h(v(e)),经调试,不同接口的 h(v(e)) 值是固定的,经验证 h(v(e)) 的值为 e 经过 MD5 加密后得到的结果:
复现 MD5 加密一般有两种方式,第一种是直接引 MD5 库:
require("md5")
第二种是通过引 JS 加密库 crypto-js:
var CryptoJS = require('crypto-js');
text = "Yy_Rose";
console.log(CryptoJS.MD5(text).toString());
以下是通过第二种方式进行加密,若将 x_zst_81 参数的值写成固定值,则该接口的加密结果也是固定的:
// MD5 加密
function MD5Test(xZst81) {
var zse93 = "101_3_3.0+";
var path = "/api/v4/search_v3?gk_version=gz-gaokao&t=general&q=NBA+Rose&correction=1&offset=0&limit=20&filter_fields=&lc_idx=0&show_all_topics=0&search_source=Normal+";
var dc0 = '"ABBeHFygKxWPTrqyaXCf64gg98q8y8QctHs=|1656484971"+';
var x_zst_81 = xZst81;
var text = zse93 + path + dc0 + x_zst_81;
return CryptoJS.MD5(text).toString();
}
f()(s) 搞明白了,接下来就需要跟进 F(r).encrypt,整体选中后跟进到定义位置,在该文件的第 47529 行,传入的参数 e 为 f()(s) 的值,返回值为 x-zse-96 参数值,可以看到是在动态变化的:
第 47262 行 l 函数是 jsvmp 的特征,熟悉的话会发现第 47684 行 O() 中一大串字符串同样也是 jsvmp 的特征,将第 47138 行到 47689 行整体扣下,可以通过 A = "3.0" 进行定位:
"use strict";
function o(e) {
return (o = "function" == typeof Symbol && "symbol" == typeof Symbol.A ? function(e) {
return typeof e
}
: function(e) {
return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
}
)(e)
}
function x(e) {
return C(e) || s(e) || t()
}
function C(e) {
if (Array.isArray(e)) {
for (var t = 0, n = new Array(e.length); t < e.length; t++)
n[t] = e[t];
return n
}
}
function s(e) {
if (Symbol.A in Object(e) || "[object Arguments]" === Object.prototype.toString.call(e))
return Array.from(e)
}
function t() {
throw new TypeError("Invalid attempt to spread non-iterable instance")
}
Object.defineProperty(exports, "__esModule", {
value: !0
});
var A = "3.0", S = "undefined" != typeof window ? window : {}, h;
function i(e, t, n) {
t[n] = 255 & e >>> 24,
t[n + 1] = 255 & e >>> 16,
t[n + 2] = 255 & e >>> 8,
t[n + 3] = 255 & e
}
function B(e, t) {
return (255 & e[t]) << 24 | (255 & e[t + 1]) << 16 | (255 & e[t + 2]) << 8 | 255 & e[t + 3]
}
function Q(e, t) {
return (4294967295 & e) << t | e >>> 32 - t
}
function G(e) {
var t = new Array(4)
, n = new Array(4);
i(e, t, 0),
n[0] = h.zb[255 & t[0]],
n[1] = h.zb[255 & t[1]],
n[2] = h.zb[255 & t[2]],
n[3] = h.zb[255 & t[3]];
var r = B(n, 0);
return r ^ Q(r, 2) ^ Q(r, 10) ^ Q(r, 18) ^ Q(r, 24)
}
var __g = {
x: function(e, t) {
for (var n = [], r = e.length, i = 0; 0 < r; r -= 16) {
for (var o = e.slice(16 * i, 16 * (i + 1)), a = new Array(16), c = 0; c < 16; c++)
a[c] = o[c] ^ t[c];
t = __g.r(a),
n = n.concat(t),
i++
}
return n
},
r: function(e) {
var t = new Array(16)
, n = new Array(36);
n[0] = B(e, 0),
n[1] = B(e, 4),
n[2] = B(e, 8),
n[3] = B(e, 12);
for (var r = 0; r < 32; r++) {
var o = G(n[r + 1] ^ n[r + 2] ^ n[r + 3] ^ h.zk[r]);
n[r + 4] = n[r] ^ o
}
return i(n[35], t, 0),
i(n[34], t, 4),
i(n[33], t, 8),
i(n[32], t, 12),
t
}
};
function l() {
this.C = [0, 0, 0, 0],
this.s = +[],
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 = +[],
this.T = 255,
this.V = null,
this.U = Date.now,
this.M = new Array(32)
}
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) == +[] ? 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(O === +[] ? M.join("|") : O === +!+[] ? -1 !== M.join().indexOf(".") ? parseInt(M.join()) : parseFloat(M.join()) : 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,
this.J === +[] ? this.s = this.b : this.J === +!+[] ? !!this.Q && (this.s = this.b) : 2 === this.J ? !this.Q && (this.s = this.b) : 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 = 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 = B === +[] ? 445 : B === +!+[] ? 380 : 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[+[]]),
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[+[]]),
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[+[]], G[1]),
this.T -= 119 - G.length;
break;
case 471:
this.C[3] = new this.C[this.W](G[+[]]),
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[+[]], 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(e) {
var n = new l;
return n.S = t,
n.S[0] = e,
n.O(h.G, h.V, h.D),
n.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[+[]],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(e) {
return __g._encrypt(encodeURIComponent(e))
};
exports.ENCRYPT_VERSION = A,
exports.default = D
}
然后补环境,补环境大致有几种方式:
- 简单的,报错提示什么 undefined 就补什么即可,但是有的站点基本的补完后不报错也不返回数据,就得具体去分析到底还校验了哪些环境,例如抖音
- 通过 Proxy 对常见环境检测点进行代理,拦截代理对象的读取、函数调用等操作,根据输出结果针对性的补,Proxy - JavaScript | MDN,本例就可以通过挂代理来补,推荐看看渔滒的文章
- 插桩,在关键逻辑处打下日志断点,通过日志内容,再比较浏览器环境和 node 环境的差异,查漏补缺
- 搭建补环境框架或自吐框架,就算不能完全解决问题,也能省掉很多麻烦,后续工作量大大减少
- jsdom 库,是方便不少,但是并不能完全解决问题,并且感觉存在一些兼容性 bug,以及若干未知问题,还是尽量都自己补
- 通过 Hook 将校验的 node 环境替换为浏览器对应的
- vm2,纯净的 V8 环境,实现一个沙箱,一个 JS 文件引入 vm2 环境再调用扣下来的 JS 文件
这里需要补 document、toString()、navigator、location、history、screen、canvas 等等,以下成功生成 x-zse-96 参数的值:
通过 python 请求接口链接验证:
x-zst-81 参数的值可以固定,搜索接口没有对其进行校验,置空也可以,webpack 通过 rpc 或者导出来都行,这里不做详细描述,后续可能会对其进行逆向分析。