JsRPC生成某乎3.0版x-zse-96学习分析,网站:aHR0cHM6Ly93d3cuemhpaHUuY29tLw==

一、jsrpc工具

用的是github上一位大神所写的工具,里面有写具体用法

   https://github.com/jxhczhl/JsRpc

点进去下载安装包

eaf480e5d0964288bbf62d37798a2158.png

下载本地版,https/wss版本需要在当前目录放证书。

e2ce3a079c2f4ffb9d900d3399bdd944.png

下载后直接双击运行,开启服务

f1ab09c377fc4464841ba9bc3a015a7e.png

api 简介:
/list :查看当前连接的ws服务 (get)
/ws :浏览器注入ws连接的接口 (ws | wss)
/go :获取数据的接口 (get | post)
/execjs :传递jscode给浏览器执行 (get | post)

二、改写加密js文件

用JsRPC的话不用去扣代码,所以先定位到加密js文件

1749673ce18144e7b5886106e23dd4ca.png

用chrome浏览器的overrides功能去覆盖这个文件实现改写

d2ff783935c143f0a5f63b6d5f60a455.png

cf6303e7d09c4d069cb368d7833aabde.png

覆盖成功后就会在文件夹下面生成对应的路径与js文件,这个文件可以进行编辑

642e10294f6f4a259aaf758207e11450.png

格式化下文件,把加密函数赋值给全局变量,方便我们调用,需要ctrl+s保存下,这个是新加的,其余不要改
window.zhihu_signature = F(r).encrypt;
window.zhihu_md5 = f;

da2a74c7c35144adac0fe4520a90e3bc.png

刷新验证下是否走了我们改写的js文件,在控制台用赋值的全局变量测试是可以出结果的

60dd91a2480f428ab09e1b0f3a80cc9f.png

没问题就可以进行rpc调用了

三、rpc调用

 1、远程调用: 浏览器预先注册js方法 传递函数名调用 注入JS,构建通信环境,

        把项目文档的JsEnv.js文件内容复制到控制台

        打开JsEnv 复制粘贴到网站控制台(注意:可以在浏览器开启的时候就先注入环境,不然要放开调试断点才能注入)

8968250f01774a43a76ce5c03dd5e787.png

注入环境后连接通信

        var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz&name=hlg");

 注册一个方法,第一个参数get_sign为方法名,第二个参数为函数,resolve里面的值是想要的值(发送到服务器的)

        demo.regAction("get_sign", function (resolve, param) { const args_url = param['str'];                console.log("参数值:", param['str']); res =               window._zhihu_signature(window.zhihu_md5()(args_url)) console.log("调用结果:", res);          resolve(res); })

总的就是把下面这段代码复制到控制台:

function Hlclient(wsURL) {
    this.wsURL = wsURL;
    this.handlers = {};
    this.socket = {};
    if (!wsURL) {
        throw new Error('wsURL can not be empty!!')
    }
    this.connect()
    this.handlers["_execjs"]=function (resolve,param){
        var res=eval(param)
        if (!res){
            resolve("没有返回值")
        }else{
            resolve(res)
        }

    }
}

Hlclient.prototype.connect = function () {
    console.log('begin of connect to wsURL: ' + this.wsURL);
    var _this = this;
    try {
        this.socket["ySocket"] = new WebSocket(this.wsURL);
        this.socket["ySocket"].onmessage = function (e) {
            try{
                let blob=e.data
                blob.text().then(data =>{
                    _this.handlerRequest(data);
                })
            }catch{
                console.log("not blob")
                _this.handlerRequest(blob)
            }

        }
    } catch (e) {
        console.log("connection failed,reconnect after 10s");
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket["ySocket"].onclose = function () {
        console.log("connection failed,reconnect after 10s");
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }

};
Hlclient.prototype.send = function (msg) {
    this.socket["ySocket"].send(msg)
}

Hlclient.prototype.regAction = function (func_name, func) {
    if (typeof func_name !== 'string') {
        throw new Error("an func_name must be string");
    }
    if (typeof func !== 'function') {
        throw new Error("must be function");
    }
    console.log("register func_name: " + func_name);
    this.handlers[func_name] = func;
    return true

}

//收到消息后这里处理,
Hlclient.prototype.handlerRequest = function (requestJson) {
    var _this = this;
    var result=JSON.parse(requestJson);
    //console.log(result)
    if (!result['action']) {
        this.sendResult('','need request param {action}');
        return
    }
    var action=result["action"]
    var theHandler = this.handlers[action];
    if (!theHandler){
        this.sendResult(action,'action not found');
        return
    }
    try {
        if (!result["param"]){
            theHandler(function (response) {
                _this.sendResult(action, response);
            })
        }else{
            var param=result["param"]
            try {
                param=JSON.parse(param)
            }catch (e){
                console.log("")
            }
            theHandler(function (response) {
                _this.sendResult(action, response);
            },param)
        }

    } catch (e) {
        console.log("error: " + e);
        _this.sendResult(action+e);
    }
}

Hlclient.prototype.sendResult = function (action, e) {
    this.send(action + atob("aGxeX14") + e);
}


// 注入环境后连接通信
var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz&name=hlg");

// 第二个参数为函数,resolve里面的值是想要的值(发送到服务器的)
demo.regAction("get_sign", function (resolve, param) {
  const args_url = param['str'];
  console.log("参数值:", param['str']);
  res = window.zhihu_signature(window.zhihu_md5()(args_url))
  console.log("调用结果:", res);
  resolve(res);
})

运行后,会打印一个true的log

 eae61e599da7424e9f839123d5f2a34d.png

2、用python代码访问接口,获得js端的返回值
import requests, urllib, execjs, json
headers = {
    "Connection": "keep-alive",
    "Pragma": "no-cache",
    "Cache-Control": "no-cache",
    "x-zse-93": "101_3_3.0",
    "x-ab-param": "",
    "x-api-version": "3.0.91",
    "x-zst-81": "",
    "sec-ch-ua-mobile": "?0",
    "x-requested-with": "fetch",
    "x-zse-96": "2.0_dW8LrkY7pTSI9IQ+Fa9Qwzgr1U9WYDPAAHiXssdcDHCPpW1c2nSP6x=i=saDJrPN",
    "x-app-za": "OS=Web",
    "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"96\", \"Google Chrome\";v=\"96\"",
    "sec-ch-ua-platform": "\"Windows\"",
    "Accept": "*/*",
    "Sec-Fetch-Site": "same-origin",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Dest": "empty",
    "Accept-Language": "zh-CN,zh;q=0.9"
}
cookies = {
    "d_c0": "ACAX5eGJjRWPTvSFbO5sIWWD9JTXphKeDpw=|1663055747",
}
params = {
    "gk_version": "gz-gaokao",
    "t": "general",
    "q": "带土",
    "correction": "1",
    "offset": "0",
    "limit": "20",
    "filter_fields": "",
    "lc_idx": "0",
    "show_all_topics": "0",
    "search_source": "Normal"
}


args_url = '101_3_3.0+/api/v4/search_v3?' + urllib.parse.urlencode(params) + '+' + cookies["d_c0"] + '+' + headers["x-zst-81"]

url = "http://localhost:12080/go"
data = {
    "group": "zzz",
    "name": "hlg",
    "action":"get_sign",
    "param":json.dumps({"str":args_url})
}
res = requests.post("http://localhost:12080/go", data=data).json()  #这里获取加密值
print(res)
x_zse_96 = "2.0_" + res["data"]
print(x_zse_96)
headers["x-zse-96"] = x_zse_96  #替换得到的加密值,再请求对应接口
url = "https://www.zhihu.com/api/v4/search_v3"
response = requests.get(url, headers=headers, cookies=cookies, params=params)
print(response.text)
print(response)

运行python代码时,控制台会打印出对应log

0b7a5b21a607411ebb97dfb0e3d74f3c.png

 成功跑出结果6b93a4ef42a64ce1bd3bac211ef3ca43.png

 上面是把代码直接复制到控制台上,也可以新建一个snippet,在里面运行代码

62bcd1035b8e4b2bb1849271583d4f01.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值