IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> js RPC及Sekrio的使用 -> 正文阅读

[网络协议]js RPC及Sekrio的使用

有时候遇到一些加密参数,我们不想知道它是怎么生成的,只想取它的值,这种情况下就适合使用RPC了
第一种使用websocket的方式,通过油猴脚本把浏览器生成好的加密参数通过socket通信方式发送到本地
以这个网址为例,这是一个rs的网址
http://www.nhc.gov.cn/
查看一下源代码,懂得都懂
在这里插入图片描述

油猴脚本代码

// ==UserScript==
// @name         ws
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://www.fangdi.com.cn/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    window.ws = new WebSocket('ws://127.0.0.1:8010/');
    ws.onopen = function(){
        console.log("连接服务器成功");
        ws.send("Browser start");
    };
    ws.onclose = function(){
        console.log("服务器关闭");
    };
    ws.onerror = function(){
        console.log("连接出错");
    };
    ws.onmessage = function(evt){
        console.log(evt.data)
        console.log(document.cookie);
    }
})();

本地使用python去连接

import asyncio
import websockets

# 把接受的消息打印后返回回去
async def recv_msg(websocket):
    while True:
        recv_text = await websocket.recv()
        print(recv_text)
        await websocket.send(recv_text)

async def main(websocket, path):
    await recv_msg(websocket)

start_server = websockets.serve(main, 'localhost', 8010)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

先运行python,再刷新对应的网址
在控制台输入ws.send(document.cookie)
python就可以接受到cookie
效果如下
在这里插入图片描述

发现只有一个sVoELocvxVW0T,应该有三个cookie的才对
这里需要在浏览器上设置一下
在这里插入图片描述

打了勾的是无法获取,需要双击后点击取消掉
现在三个cookie都能拿到
试下能不能拿到网页数据
在这里插入图片描述

上面的方式虽然可以拿到cookie,但是每次都需要去控制台send
能不能做成api的形式
请求一下就可以拿到cookie的
当然有了,这里大力推荐渣总的Sekrio框架

Sekrio

渣总开发的框架,现成轮子使用、更简单的接入rpc
github: https://github.com/virjar/sekiro
官方文档:https://sekiro.virjar.com/sekiro-doc/index.html
我用的是window,操作以window为例

安装

先把代码下载下来
然后双击运行 build_demo_server.sh
它会自动构建
在这里插入图片描述

构建完成之后
在sekiro-service-demo\target\sekiro-release-demo\bin下有两个启动文件,bat结尾的win,sh是linux
运行sekiro.bat
在这里插入图片描述

可以链接查看是否正常启动 http://127.0.0.1:5620/business-demo/groupList

样例

先把案例跑通,
https://sekiro.virjar.com/sekiro-doc/assets/sekkiro_js_demo.html页面源码都复制下来
创建一个html文件粘贴进去
然后把其中代码修改一下

<script type="text/javascript" src="sekiro_web_client.js"></script> 
改为
<script type="text/javascript" src="https://sekiro.virjar.com/sekiro-doc/assets/sekiro_web_client.js"></script>

它里面连接的是自己的服务器
如果要把服务器改为自己的话,就把

var client = new SekiroClient("wss://sekiro.virjar.com/business/register?group=ws-group&clientId=" + guid());
改为
var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=ws-group&clientId=" + guid());

在这里插入图片描述

运行,在浏览器打开控制台可以看到
在这里插入图片描述

浏览器访问 http://127.0.0.1:5620/business-demo/groupList
看到服务已开启

{"data":["test","ws-group"],"ok":true,"status":0}

用python测试一下

import requests
params ={
    "group":"ws-group",#接口名称
    "action":"executeJs",#注册的服务名
}
res = requests.get("http://127.0.0.1:5620/business-demo/invoke", params=params)
print(res.text)

在这里插入图片描述

修改端口

Sekrio默认的端口是5620
需要修改的话
在项目根目录下\sekiro-service-demo\target\sekiro-release-demo\conf\config.properties进行修改即可

rs网站实战

这里的话还是用上面的网址
这里我们需要油猴来做服务

编辑脚本

新建油猴脚本
在这里插入图片描述

访问https://sekiro.virjar.com/sekiro-doc/assets/sekiro_web_client.js
把sekrio依赖的js脚本复制放到油猴里
并上面样例的html里的这几行也复制进油猴里
在这里插入图片描述

修改下executeJs接口,获取cookie后把值传出来
在这里插入图片描述

完整的油猴脚本:

// ==UserScript==
// @name         sekrio
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://www.nhc.gov.cn/*
// @grant        none
// ==/UserScript==

(function() {

    /*
  Copyright (C) 2020 virjar <virjar@virjar.com> for https://github.com/virjar/sekiro

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


function SekiroClient(wsURL) {
    this.wsURL = wsURL;
    this.handlers = {};
    this.socket = {};
    // check
    if (!wsURL) {
        throw new Error('wsURL can not be empty!!')
    }
    this.webSocketFactory = this.resolveWebSocketFactory();
    this.connect()
}

SekiroClient.prototype.resolveWebSocketFactory = function () {
    if (typeof window === 'object') {
        var theWebSocket = window.WebSocket ? window.WebSocket : window.MozWebSocket;
        return function (wsURL) {

            function WindowWebSocketWrapper(wsURL) {
                this.mSocket = new theWebSocket(wsURL);
            }

            WindowWebSocketWrapper.prototype.close = function () {
                this.mSocket.close();
            };

            WindowWebSocketWrapper.prototype.onmessage = function (onMessageFunction) {
                this.mSocket.onmessage = onMessageFunction;
            };

            WindowWebSocketWrapper.prototype.onopen = function (onOpenFunction) {
                this.mSocket.onopen = onOpenFunction;
            };
            WindowWebSocketWrapper.prototype.onclose = function (onCloseFunction) {
                this.mSocket.onclose = onCloseFunction;
            };

            WindowWebSocketWrapper.prototype.send = function (message) {
                this.mSocket.send(message);
            };

            return new WindowWebSocketWrapper(wsURL);
        }
    }
    if (typeof weex === 'object') {
        // this is weex env : https://weex.apache.org/zh/docs/modules/websockets.html
        try {
            console.log("test webSocket for weex");
            var ws = weex.requireModule('webSocket');
            console.log("find webSocket for weex:" + ws);
            return function (wsURL) {
                try {
                    ws.close();
                } catch (e) {
                }
                ws.WebSocket(wsURL, '');
                return ws;
            }
        } catch (e) {
            console.log(e);
            //ignore
        }
    }
    //TODO support ReactNative
    if (typeof WebSocket === 'object') {
        return function (wsURL) {
            return new theWebSocket(wsURL);
        }
    }
    // weex 鍜� PC鐜鐨剋ebsocket API涓嶅畬鍏ㄤ竴鑷达紝鎵浠ュ仛浜嗘娊璞″吋瀹�
    throw new Error("the js environment do not support websocket");
};

SekiroClient.prototype.connect = function () {
    console.log('sekiro: begin of connect to wsURL: ' + this.wsURL);
    var _this = this;
    // 涓峜heck close锛岃
    // if (this.socket && this.socket.readyState === 1) {
    //     this.socket.close();
    // }
    try {
        this.socket = this.webSocketFactory(this.wsURL);
    } catch (e) {
        console.log("sekiro: create connection failed,reconnect after 2s");
        setTimeout(function () {
            _this.connect()
        }, 2000)
    }

    this.socket.onmessage(function (event) {
        _this.handleSekiroRequest(event.data)
    });

    this.socket.onopen(function (event) {
        console.log('sekiro: open a sekiro client connection')
    });

    this.socket.onclose(function (event) {
        console.log('sekiro: disconnected ,reconnection after 2s');
        setTimeout(function () {
            _this.connect()
        }, 2000)
    });
};

SekiroClient.prototype.handleSekiroRequest = function (requestJson) {
    console.log("receive sekiro request: " + requestJson);
    var request = JSON.parse(requestJson);
    var seq = request['__sekiro_seq__'];

    if (!request['action']) {
        this.sendFailed(seq, 'need request param {action}');
        return
    }
    var action = request['action'];
    if (!this.handlers[action]) {
        this.sendFailed(seq, 'no action handler: ' + action + ' defined');
        return
    }

    var theHandler = this.handlers[action];
    var _this = this;
    try {
        theHandler(request, function (response) {
            try {
                _this.sendSuccess(seq, response)
            } catch (e) {
                _this.sendFailed(seq, "e:" + e);
            }
        }, function (errorMessage) {
            _this.sendFailed(seq, errorMessage)
        })
    } catch (e) {
        console.log("error: " + e);
        _this.sendFailed(seq, ":" + e);
    }
};

SekiroClient.prototype.sendSuccess = function (seq, response) {
    var responseJson;
    if (typeof response == 'string') {
        try {
            responseJson = JSON.parse(response);
        } catch (e) {
            responseJson = {};
            responseJson['data'] = response;
        }
    } else if (typeof response == 'object') {
        responseJson = response;
    } else {
        responseJson = {};
        responseJson['data'] = response;
    }


    if (Array.isArray(responseJson)) {
        responseJson = {
            data: responseJson,
            code: 0
        }
    }

    if (responseJson['code']) {
        responseJson['code'] = 0;
    } else if (responseJson['status']) {
        responseJson['status'] = 0;
    } else {
        responseJson['status'] = 0;
    }
    responseJson['__sekiro_seq__'] = seq;
    var responseText = JSON.stringify(responseJson);
    console.log("response :" + responseText);
    this.socket.send(responseText);
};

SekiroClient.prototype.sendFailed = function (seq, errorMessage) {
    if (typeof errorMessage != 'string') {
        errorMessage = JSON.stringify(errorMessage);
    }
    var responseJson = {};
    responseJson['message'] = errorMessage;
    responseJson['status'] = -1;
    responseJson['__sekiro_seq__'] = seq;
    var responseText = JSON.stringify(responseJson);
    console.log("sekiro: response :" + responseText);
    this.socket.send(responseText)
};

SekiroClient.prototype.registerAction = function (action, handler) {
    if (typeof action !== 'string') {
        throw new Error("an action must be string");
    }
    if (typeof handler !== 'function') {
        throw new Error("a handler must be function");
    }
    console.log("sekiro: register action: " + action);
    this.handlers[action] = handler;
    return this;
};
    function guid() {
        function S4() {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        }

        return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
    }

    var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=ws-group&clientId=" + guid());

    client.registerAction("clientTime", function (request, resolve, reject) {
        resolve("SekiroMessage:" + new Date());
    });

    client.registerAction("executeJs", function (request, resolve, reject) {
        var code = request['code'];
        if (!code) {
            reject("need param:{code}");
            return;
        }

        //code = "return " + code;

        console.log("executeJs: " + code);

        try {
            // var result = new Function(code)();
            var result = document.cookie;
            resolve(result);
        } catch (e) {
            reject("error: " + e);
        }

    });


})();

保存运行

保存脚本,刷新页面
这样显示表示脚本注入成功
在这里插入图片描述

服务注册也是成功的
在这里插入图片描述

接口调用

import requests
params ={
    "group":"ws-group",#接口名称
    "action":"executeJs",#注册的服务名
    "code": "document.cookie"
}
res = requests.get("http://127.0.0.1:5620/business-demo/invoke", params=params)
print(res.text)

在这里插入图片描述

经过测试正常拿到页面数据
再也不用当心逆向js代码而掉头发了

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-10-07 14:09:39  更:2021-10-07 14:11:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年9日历 -2024/9/21 9:11:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码