网页逆向-某乎webpack打包

首先登录,找XHR请求

全局搜索x-zse-,只搜到这一个地方

这段代码简单分析一下,结合调试可以发现,这段代码就是返回的undefined,但是全局只有这一个地方有该字符串,所以推测应该是在后面用到了,某个变量存储的就是"x-zse-96"字符串,再往后调试一下可以看到tX函数被调用的地方返回了一些和加密字段有关的东西,就位于这段代码后面不远的地方

这里的tC存储的就是"x-zse-96"字符串,tpheaders{}对象,所以关键的字段设置就在tp.set(tC, t2 + "_" + tk)

tp.set(tC, t2 + "_" + tk)这里的t22.0,结合字段值2.0_KiU15+zlzUwmi7cQe+oyuIBFxYm9c0TedgjUhO40isCAJoAh=BTeYAY6AjGlAdi8可以知道tK就是后面的加密字符串

分析tK是怎么来的,tKtk = tT.signature;这里被赋值的,控制台打印一下tT的值

1
2
tT
{source: '101_3_3.0+/api/v4/me?include=is_realname+_aETvvfrJRqPTixt7SyKmuy0sz8prA9hx6M=|1742001484', signature: '+KvxvJ6CXrm3UWgYuj56KT2DQ5f26hxquTlIdbUdKYC2g/qcot2+zaTDTV0zblq1'}

tT的赋值在如下位置

1
2
3
4
5
6
var tO = er()
tT = ed(te, tf.body, {
zse93: tb,
dc0: tO,
xZst81: tE
}, tm)

分析可知,参数如下

1
2
3
4
5
6
te : '/api/v4/me?include=is_realname'
tf.body : undefined
tb : '101_3_3.0'
tO : 来自于er()函数生成,_aETvvfrJRqPTixt7SyKmuy0sz8prA9hx6M=|1742001484 , | 后面是时间戳
tE : null
tm : undefined

进入er()函数

1
2
3
4
5
t9 = RegExp("d_c0=([^;]+)")
, er = function() {
var tt = t9.exec(document.cookie);
return tt && tt[1]
}

这里的RegExp("d_c0=([^;]+)")是正则匹配,会匹配d_c0这样的字符串,在document.cookie里面匹配

进入ed()函数,也就是核心加密函数

重点分析这里, signature: (0,tJ(ti).encrypt)(ty()(tp)),先看tJ(ti).encrypt,进入tJ函数

tJ(ti).encrypt就是tv.ZP,控制台输出下tv可以发现ZP属性是个函数,步入这个函数

这里传入的参数tt的值就是后面ty()(tp)得到的结果,是原生的md5,可以在tJ(ti).encrypt)(ty()(tp))处断下来控制台测试ty()(tp)或者ty()(123456)与标准md5进行对比

所以重点要做的还是tJ(ti).encrypt也就是tv.ZP这里

通过下面的数字:可以看出来明显是webpack打包之后的js代码

把所有的代码复制下来,丢到webstorm的匿名自执行函数里,后面要做的就是找到webpack的分发器和函数字典(键值对大概是数字:函数名这种),分发器会根据数字找到数字对应的函数中去执行该函数

找分发器的方法就是在函数的起始位置打上断点,然后在堆栈上往上找

找到这种n(xxx)的地方,步入n函数,这个就是分发器代码

把分发器代码放到加密代码的后面,然后全局定义变量window.encParam,在匿名函数中把分发器赋值给window.encParam

1
2
3
4
5
6
7
8
9
self = window = global;
window.encParam;
!function () {
// webpack代码
// 分发器代码
window.encParam = p;
function p(){...}
}
console.log(window.encParam);

需要调用的方法是1514,也就是__g._encrypt(encodeURIComponent(tt))所在的方法

打印console.log(window.encParam(1514)),返回{ XL: '3.0', ZP: [Function: D] },就是需要调用ZP属性的D函数,这个就很容易了,console.log(window.encParam(1514)['ZP']('ed39f191a621e25b1c0bd261f1cf6717'))

当然输出的结果和浏览器不一样,是因为有VMP的环境检测,需要补环境,这个就是另一个过程了,这里只说webpack怎么扣

也可以看到,扣出来的webpack太大了,可以只留我们需要的函数,思路就是给一个起始的函数,逐个输出调用函数的ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
!function() {
"use strict";
var e, a, d, c, f, b, t, r, o, n, i, s, l, u = {}, m = {};
window.encParam = p;
function p(e) {
var a = m[e];
if (void 0 !== a)
return a.exports;
var d = m[e] = {
id: e,
loaded: !1,
exports: {}
};
console.log("调用函数:",e);
//...
console.log(window.encParam(1514)['ZP']('ed39f191a621e25b1c0bd261f1cf6717'))

然后把不要的函数给去掉就行了