跳转至

知乎 x-zse-96 和 x-zst-81 参数说明

本文介绍知乎 web 的搜索请求中的 x-zse-96x-zst-81 参数的生成方式。

前言

本文用于介绍知乎 web 搜索界面中的 x-zse-96x-zst-81 参数的生成方式。

1. 前提条件

其实只需要一个自己熟悉的调试浏览器即可。

知乎 web x-zse-96x-zst-81 参数逆向前可能需要如下内容:

  • google 浏览器
  • 补环境框架
  • nodejsdom

2. 操作步骤

2.1. x-zse-96 参数解决

2.1.1. 参数定位

直接全局搜索 x-zse-96 即可定位到具体的参数生成位置所在的文件。

zhihu1

会搜到两个位置,最后面的一个是对的位置。然后根据下面的断点可知,最终的生成位置在 12245 行中。

这里最好下一个条件断点,以防断点过于繁杂。
  • 条件断点示例(请更换为你自己需要定位的搜索请求下的特征值):s.indexOf("101_3_2.0+/api/v4/search_v3") != -1

zhihu2

s 明文数据解释:

s = '101_3_2.0+'(版本号) + '/api/v4/search_v3?t=general&q=python&correction=1&' + 'offset=0&limit=20&filter_fields=&lc_idx=0&show_all_topics=0&search_source=Normal+'(接口后缀) + '"AIAf1GdgbRSPTtoYPsJrpvRp_MB-_8SxwGQ=|1643717522"'(dc0 cookie)

2.1.2. f 函数解决

根据以上步骤可知 x-zse-96 是由 f 函数和 F(r).encrypt 函数得到。然后根据 f 函数的生成结果可知 f 函数为 MD5,是扣代码还是直接 py 库实现都可以。这里以扣代码为例。

直接点击 f() 即可跳转到其具体位置,将其及以上涉及的部分整体抠出来(即将圈起来的部分全扣出来即可,notepad++ 使用不再介绍)。

zhihu3

2.1.3. F(r).encrypt 函数解决

同样的方法,鼠标定位到 F(r).encrypt 函数即可跳转到具体的函数位置。将其所覆盖的代码整体抠出来,然后将其改成自执行方法即可。

zhihu5

具体改成以下内容即可,以下为伪代码,按照以下格式即可。

// 以下的函数为 F(r).encrypt 的方法导出,将其改为自执行函数
// (function e(module, exports, __webpack_require__) {
(function e() {
    "use strict";
    function t(e) {
        return (t = "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)
    }
    // 删除此行代码
    // Object.defineProperty(exports, "__esModule", {
    //     value: !0
    // });
    var A = "2.0"
      , __g = {};
    function s() {}
    function i(e) {
        this.t = (2048 & e) >> 11,
        this.s = (1536 & e) >> 9,
        this.i = 511 & e,
        this.h = 511 & e
    }

    ... ...

    var b = function(e) {
        return __g._encrypt(encodeURIComponent(e))
    };
    // exports.ENCRYPT_VERSION = A,
    // exports.default = b
    // 将最终的调用方法 b 导出到全局
    window.window_b = b;
})(window)


function get_96(s) {
    console.log(s);
    console.log(A(s));
    return "2.0_" + window.window_b(A(s));
}

最终,补充缺失的 atobbtoa 方法即可成功运行。

2.2. x-zst-81 参数解决

x-zst-81 参数生成过程所依赖的步骤较多,大致分为以下步骤。

2.2.1. SESSIONID 参数获取

SESSIONID 在发送 r post 请求包生成 nonce 时,和最终 Z 函数中的参数最后一个拼接的参数有需要。其需要扣出的代码为:

function c(){
    C = function(e, t, n) {
        var r = {};
        r['JapPp'] = function(e, t) {
            return e < t
        }
            ,
            r["QtEFd"] = function(e, t) {
                return e * t
            }
            ,
            r["tfNgJ"] = function(e, t) {
                return e - t
            }
            ,
            r["NGqZi"] = function(e, t) {
                return e * t
            }
            ,
            r["rqwtS"] = function(e, t) {
                return e - t
            }
        ;
        for (var a = "1|2|4|0|3"["split"]("|"), i = 0; ; ) {
            switch (a[i++]) {
                case "0":
                    for (var o = 0; r.JapPp(o, s); o++) {
                        u += A[Math["round"](r["QtEFd"](Math.random(), r.tfNgJ(A["length"], 1)))]
                    }
                    continue;
                case "1":
                    var u = ""
                        , s = t;
                    continue;
                case "2":
                    var A = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
                    continue;
                case "3":
                    return u;
                case "4":
                    e && (s = Math["round"](r.NGqZi(Math["random"](), r.rqwtS(n, t))) + t);
                    continue
            }
            break
        }
    }(!1, 43)
    return C
}

console.log("生成的 SESSIONID 为:", c());

2.2.2. 发送 r 请求包

此请求包需要使用 __g._e2(encodeURI(e)) 方法生成的结果作为 post 的参数,返回后面过程中需要的 nonce 值。

先使用 __g._e2(encodeURI(e)) 方法生成 r 请求包的 post 参数,具体如下:

zhihu6

r 请求包的参数与 e2 函数生成结果对照如下:

zhihu7

r 请求包返回的 nonce 参数示例如下:

zhihu8

2.2.3. e1 函数

此步骤用于生成 Z 函数所需的 参数1参数2 。具体需要运行 e1 函数,参数为上步骤返回的 nonce 参数。

zhihu9

2.2.4. Z 函数

这步骤为上步骤的简单说明

zhihu10

进入这个 e1 函数后,可以得到此函数的返回结果是长度为 10 的一个数组,记住这个返回内容。

zhihu11

接着单步调试到 Z 函数中,可以其参数 t 是由上步骤放回的数组中的第一个和第二个再和 SESSIONID 使用 # 符号连接而得。

zhihu12

最后,验证 x-zst-81 参数是否与请求包一致。

zhihu13

代码如何扣就不再一步步展示了,自己多调试下自然知道怎么扣了。

3. 总结及参考文档

网上有关于知乎的 x-zse-96 参数的文章烂大街了,有算法还原的,有扣代码的,有用 jsdom 实现的等等;

但是有关 x-zst-81 的相关文章几乎没有,就算有提到也没有给出任何解法,所以我才写了此文章来对其进行补充说明。

4. 再度更新

现在网上关于知乎参数的相关文章已经很多了,基本根据其方法都可成功生成参数,这里只作简单介绍。

发现知乎 js 版本更新到 3.0 了,这两个参数增加了环境检测,如果还是用本文的方法来生成值的,在本地直接运行无法通过校验,但是将扣出的代码放到浏览器中运行是可正常使用的。但其实检测的内容很少,直接把检测的环境补齐即可。

生成的值会变动,此 js 中是通过 math.random 来实现的,可以将其返回固定值,来判断本地最终生成的值是否和网页中的一致。

可以把扣出的代码中的 try catch 异常捕获删除,然后根据 proxy 代理上 location, navigator, history 等等,看看获取了哪些值。根据和网页中的返回内容不同来补充其值即可。

注:这里放上 proxy 检测环境的参考文章

评论

回到页面顶部