基于autojs的群控插件
2022-05-31 本文已影响0人
LCSan
- autojs4.1端,打包成apk。upd服务自动发现,websocket命令中转,服务自检。
//引入需要用到的安卓包
importClass("java.net.InetAddress");
importClass("java.net.Inet6Address");
importClass("java.net.NetworkInterface");
importClass("java.net.InetSocketAddress");
importClass("java.net.DatagramPacket");
importClass("java.net.DatagramSocket");
// websocket全局对象,本地IP(用于终端验证)
let ws, localIP;
// 全局检测,ws服务端中断以后,需要重新自启组播服务,扫描服务用于子发现
let isConnect;
// 等待获取无障碍权限
auto.waitFor();
// 服务监控
let serverListenser = setInterval(function () {
log("服务侦听…");
initServer();
}, 3000);
// initServer();
//监听log事件,发送给服务端
events.broadcast.on("log", function (words) {
try {
if (!localIP) {
localIP = getIntranetIP();
}
log(words);
ws.send(JSON.stringify({ "type": "msg", "ip": localIP, "result": words }));
} catch (err) {
log(err);
}
});
function initServer() {
// 服务未连接
if (isConnect != true) {
// 临时暂停监听服务
clearInterval(serverListenser);
let ds = initDs();
log("服务端发现…")
while (true) {
try {
log("尝试通信…")
// 发送组播消息,检测ws服务端口
sendDs(ds, '255.255.255.255', 8061, JSON.stringify({ "type": "initAuto.js" }));
// 等待消息响应
let msg = getDsMsg(ds);
log(msg);
if (msg["msg"]["statues"] === "success") {
ds.close();
log("检测到服务,尝试链接…")
log("ws:/" + msg["ip"] + ":" + msg["msg"]["port"])
// 创建websocket链接
ws = initWs("ws:/" + msg["ip"] + ":" + msg["msg"]["port"] + "/worker");
// 服务器启动成功,更新标记位
isConnect = true;
log("链接成功!!")
// 重启监听服务
serverListenser = setInterval(function () {
initServer();
}, 3000);
break;
}
} catch (error) {
log("未检测到服务…");
}
}
}
}
// 创建组播
function initDs() {
// 构造数据报套接字并将其绑定到本地主机上任何可用的端口
log("初始化服务…")
let ds = new DatagramSocket();
ds.setBroadcast(true);
return ds;
}
// 发送组播消息
function sendDs(ds, ip, port, msg) {
ip = InetAddress.getByName(ip);
let bts = new java.lang.String(msg).getBytes("UTF-8");
ds.send(new DatagramPacket(bts, bts.length, ip, port));
}
// 接收组播消息
function getDsMsg(ds) {
let bts = util.java.array('byte', 1024);
let packet = new DatagramPacket(bts, bts.length);
ds.setSoTimeout(2000);
ds.receive(packet);
return { "ip": packet.getAddress().toString(), "msg": JSON.parse(new java.lang.String(packet.getData(), 0, packet.getLength(), "UTF-8")) };
}
7
// 创建websocket
function initWs(url) {
global
let mClient = new OkHttpClient();
let request = new Request.Builder().get().url(url).build();
let globalWebsocket = null;
mClient.newWebSocket(request, new JavaAdapter(WebSocketListener, {
onOpen: function (webSocket, response) {
globalWebsocket = webSocket;
},
onMessage: function (webSocket, text) {
// 接收到消息后,这里转发到引擎执行脚本
log("收到消息…");
try {
autojsHandle(text);
} catch (error) {
log(error);
events.broadcast.emit('log', error + "");
}
},
onClosed: function (webSocket, code, reason) {
// 这里更新全局连接标记位,用于重新拉起服务检测
isConnect = false;
globalWebsocket = null;
log("服务错误…");
try {
webSocket.close();
} catch (error) {
log(error);
}
},
onFailure: function (webSocket, throwable, response) {
isConnect = false;
globalWebsocket = null;
log("服务链接中断…");
try {
webSocket.close();
} catch (error) {
log(error);
}
}
}));
while (true) {
try {
if (globalWebsocket != null) {
break;
}
sleep(1000)
} catch (e) {
}
}
return globalWebsocket;
}
function autojsHandle(text) {
let msg = JSON.parse(text);
// log(msg)
// 所有的log都加上events.broadcast.emit("log",)来发送结果给websocket
// msg["source"] = msg["source"].replace(/(log\(((?:['"]?).*\1)\)[;\n])/ig, "$1;events.broadcast.emit('log',$2);\n");
msg["source"] = msg["source"].replace(/log\(/ig, "events.broadcast.emit(\"log\",");
// log(msg);
switch (msg["type"]) {
case "main":
eval(msg["source"]);
break;
default:
engines.execScript(msg["title"], msg["source"], msg["config"]);
break;
}
}
function getIntranetIP() {
// 获取所有网卡信息
let networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
// 遍历网卡
let networkInterface = networkInterfaces.nextElement();
// 获取网卡地址
let inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
let inetAddress = inetAddresses.nextElement();
// 判断网卡地址类型是不是IPV6,IPV6的舍弃
if (inetAddress instanceof Inet6Address) {
continue;
}
// 获取IP地址
let ip = inetAddress.getHostAddress();
// 非本地IP就绑定组播到网卡
if (!"127.0.0.1".equals(ip)) {
// 绑定网卡组播
return ip;
}
}
}
}
- 服务端用python,udp广播服务,websocket服务端。打包成exe。
服务端代码
# coding=utf-8
'''
Created on 2022年5月23日
@author: 瞌睡蟲子
'''
import asyncio
from http import client
import websockets
import json
import click
wsWorkerClents = set()
wsCommanderClents = set()
WS_PORT = None
class EchoServerProtocol:
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
message = data.decode("utf-8")
# print(message)
message = json.loads(message)
print('Received %r from %s' % (message, addr))
if "type" in message and message["type"] == "initAuto.js":
# 重新组合数据打印数据
msg = json.dumps({"statues": "success", "port": WS_PORT})
self.transport.sendto(msg.encode('utf-8'), addr)
else:
msg = json.dumps(
{"statues": "error", "port": None, "msg": "type error"})
self.transport.sendto(msg.encode('utf-8'), addr)
async def echo(websocket, path):
# print(path)
# print('%s:%d' % websocket.remote_address)
cnt = '%s:%d' % websocket.remote_address
if path == "/worker":
print('[Worker %s] online' % (cnt))
wsWorkerClents.add(websocket)
try:
async for message in websocket:
print('[Worker %s] Received: %r' % (cnt, message))
if wsCommanderClents:
[await user.send(message) for user in wsCommanderClents]
except:
print("[Worker %s] offline" % (cnt))
finally:
wsWorkerClents.remove(websocket)
elif path == "/commander":
print('[Commander %s] online' % (cnt))
wsCommanderClents.add(websocket)
try:
async for message in websocket:
print('[Commander %s] Received: %r' % (cnt, message))
if wsWorkerClents:
[await user.send(message) for user in wsWorkerClents]
except:
print("[Commander %s] offline" % (cnt))
finally:
wsCommanderClents.remove(websocket)
@click.command()
@click.option('--port', default=5432, type=int, help='port of websocket server.')
def server(port):
global WS_PORT
WS_PORT = port
loop = asyncio.get_event_loop()
print("Starting server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
EchoServerProtocol, local_addr=('0.0.0.0', 8061))
transport, protocol = loop.run_until_complete(listen)
wsServer = websockets.serve(echo, "0.0.0.0", port)
loop.run_until_complete(wsServer)
try:
loop.run_forever()
except:
pass
finally:
transport.close()
loop.close()
if __name__ == "__main__":
server()
打包脚本入口:install.bat
@echo off
rem conda的python引擎库名字
set env=p38_x64
cd %~dp0
%~d0
conda create -n %env% python=3.7 && conda activate %env% && package.bat %env%
@echo package ok!!
pause
打包脚本:package.bat
@echo off
@echo package start...
echo %1
FOR /F "delims=/ tokens=1" %%i IN ('conda env list ^| find "%1"') DO @set pkg=%%i
SET PADDLEOCR_PATH=%pkg:~25%\Lib\site-packages
echo %PADDLEOCR_PATH%
SET CODE_PATH=%~dp0
echo %CODE_PATH%
cd %~dp0
%~d0
@REM pip install websockets
@REM pip install click
@REM pip install pyinstaller
pyinstaller -F --clean -y -i logo.ico autoServer.py
@echo package ok!!
pause
- uibot python插件,控制端。通过websocket发送autojs命令。
# coding=utf-8
'''
Created on 2022年5月23日
@author: 瞌睡蟲子
'''
from time import sleep
import websocket
import threading
import json
import os
import re
from queue import Queue
from os.path import join, dirname
q = Queue()
ws_port = None
ws_client = None
def on_message(ws, message):
# print(message)
message = json.loads(message)
# if "message" in message:
q.put(message)
def on_close(wss):
global ws_port
server(ws_port)
print("### closed ###")
def server(port=5432):
global ws_client
global ws_port
ws_port = port
p = checkServer()
if p == 0:
cmd = "cd /d \"" + join(dirname(__file__), 'autoServer') + \
"\"&start autoServer.exe --port " + str(port)
print(cmd)
os.system(cmd)
sleep(2)
websocket.enableTrace(True)
ws_client = websocket.WebSocketApp(
"ws://127.0.0.1:" + str(port) + "/commander", on_message=on_message, on_close=on_close)
# ws.run_forever()
threading.Thread(target=ws_client.run_forever, daemon=True).start()
sleep(2)
def run(source, config={}, title="uibot.js", tp="main"):
ws_client.send(json.dumps(
{"source": source, "type": tp, "title": title, "config": config}))
def checkServer(pname="autoServer.exe"):
data = _command("tasklist | findstr " + pname)
if data == "":
return 0
print(data)
data = re.findall("(\\d+)\\s+Console", data)
print(data)
for pid in data:
temp = _command(
"netstat -ano | findstr LISTENING | findstr " + pid + "$")
if len(temp) > 0:
temp = re.findall(
"TCP\\s+[\\d.]+:(\\d+)\\s+[\\d.]+:\\d+\\s+LISTENING", temp)
if len(temp) > 0:
return int(temp[0])
return 0
def _command(sCommand):
with os.popen(sCommand, 'r') as f:
res = f.read()
return res
def getMsg(timeout=1000):
# 获取执行结果的消息
msg = None
try:
msg = q.get(True, timeout/1000)
except Exception:
msg = None
return msg
if __name__ == "__main__":
server()
# run("log(\"你好\");")
# print(q.get())
# while True:
# print(q.get())
for i in range(1, 5):
run("log('你好')")
print(getMsg())
sleep(1)
# print(checkServer())
只做了基础框架,没有做任何安全方面设计。