Demo 地址:
aHR0cHM6Ly93d3cuemhpaHUuY29tL3hlbi9tYXJrZXQvcmVtaXgvcGFpZF9jb2x1bW4vMTM0NzY0NTIzNjg0NDQyNTIxNg==
X-Zse-96 介绍
如图,该参数是知乎某些请求的一个头部参数,必须加上才能响应正确的数据。
不加或者计算错误写则会返回错误信息。
TIPS:上述链接内容只是随便找的,不要加入额外的猜想。
参数分析
找个有意义的请求看一下,比如评论:
可以看到,加上了 X-Zse-96 这个请求字段。
看了一下发出请求时调用的堆栈信息,发现都来自一个文件。那就随便点一个进去:
按照惯例,可以先来浅搜一下这个关键字。发现一共两处结果较少,可以都打上断点。
给 z.set("x-zse-96 打上断点。发现这代码还挺清晰的,瞟了两眼,对 rt的的值进行追溯发现是来源于 nt.signature,nt 的值是由一个自执行函数返回的。
nt.signature 的值是由pt(d).encrypt(N()(j)) 产生的,所以可以给这一行也打上断点。
刷新页面之后顺利进入到了断点。部分变量值也可以在右侧堆栈信息面板中一目了然。
p 参数是一个对象,里面包含了三个字段分别是:dc0 xZst81 zse93 。我们忽略空值的字段后就剩下 dc0 zse93 两个字段了。zse93 像是web版本号,可以固定。
看看dc0 的值是来自 St 函数返回值,可以看到值是来源于cookie的:
尝试清除掉站点数据,再次刷新页面并搜索 d_c0 :
并没有发现有设置处,再次查看了下断点处数据:
没有这个 cookie 参数加密出来的结果也可以请求到数据,说明了 d_c0 不是必须的参数。
由于 signature 字段值是由 j 变量值经过加密而成,所以我们还需要看下 j 变量的值是怎么得到的:
可以看到当前 j 值是由版本号+请求路径得到,例如:
101_3_3.0+/api/v4/comment_v5/paid_column_sku_...
如果有d_c0 cookie的话,就把cookie值一并用加号拼接上去:
101_3_3.0+/api/v4/comment_v5/paid_column_sku_...+d_c0的值
在搞懂 j 值之后,需要看一下 N 函数。因为这相当于是第一层加密:
N 是个 md5 算法,因为其长度为32位。并在尝试传入 123456 字符串后返回了令人兴奋的 e10adc... 。
继续 pt(d).encrypt 这个函数:
可以看到每次加密结果会变,大概了是使用了诸如 Math.random 或者 Date 系列的函数。
可以使用 Proxy 类为对象进行监控代理:
对于 Math 对象,只需要判断是否使用了 random 方法来获取随机数。相比之下 Date 对象的不确定性比较多,因此在监控获取对象属性时候不做判断。固定住返回结果有利于本地的算法调试。
可以看到,在固定住两个函数的返回值之后。几次执行加密算法返回的结果都是一致的。
到此,所需参数基本上已分析完毕,接下来就是扣算法补环境部分了。
扣取算法
pt(d).encrypt 这个函数是负责加密的,所以我们需要先定位到所在处。
点击控制台的 f (u){return __g 即可定位到函数所指向的代码块。
从 exports 关键字得知加密算法是作为模块导出使用的,所以往上滑动到这一模块定义的地方。然后折叠代码块进行复制:
新建一个文本,将这一块粘贴进去:
再补一个 MD5 函数。
为扣取出来的函数命名一下,这里我偷个懒就将其命名成A,这是个坏习惯,不建议你们学习。
TIPS:折叠功能可以通过点击 devtools 右上角的设置按钮(小齿轮)之后勾选 Code folding 启用
到此,算法主体已经扣取完毕。
补充浏览器运行环境
在此之前,我们先来做一些前置措施,例如将加密函数调用过程封装为一个函数之类:
打开一个浏览器新标签,将文本中的代码全部复制到控制台中并且按下回车。你会发现打印的加密结果跟原网页上的结果不同:
新标签的运行结果
原网页的运行结果
这是正常现象,因为 location 对象不同。
可以在右侧的 Event Listener Breakpoints (事件断点)中把第一条语句执行时给勾上。这样会在网页加载并开始执行第一条js语句时候停住,这样我们就可以暂时获取到一个相对纯净的原网页环境用于调试扣下来的算法部分。
可以看到取得的值与原网页加载并初始化完成的值是一样的,通过这一点可以知道补环境时候需要补充的列表里 location 对象。
location 对象可以通过在原网页中执行 copy(location) 来获取部分属性,实际上可能远不止复制出来的那几个属性。同样可以通过 Proxy 对象来以代理的方式监控。
或者使用 jsdom 库 + Proxy 来完成监控,并且补充所需要的环境。
知乎需要补充的环境对象有:screen、history、document、canvas、navigator、location ,主要就是检测环境对象的 toString 属性以及环境对象中的 Symbol.toStringTag 属性。检测的并不严格,没有检测具体值。换句话说有值就行。。
文末结语
本来想展开说的,因为到点了。一笔带过,这样也好。
具体环境代码,以学习目地的话可以私聊。不能在文中贴出,原因懂得都懂。
原文始发于微信公众号(随心记事):知乎 X-Zse-96 参数
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论