概述
有时候遇到一些加密参数,我们不想知道它是怎么生成的,只想取它的值,这种情况下就适合使用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-demotargetsekiro-release-demobin下有两个启动文件,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-demotargetsekiro-release-democonfconfig.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代码而掉头发了
最后
以上就是闪闪斑马为你收集整理的js RPC及Sekro的使用Sekrio的全部内容,希望文章能够帮你解决js RPC及Sekro的使用Sekrio所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复