Files
remote_like_teamview/client.py
2025-03-10 22:19:33 +08:00

114 lines
4.0 KiB
Python

import zlib
import time
import socket
import struct
from loguru import logger
import mss
import mss.tools
import pyautogui
import configparser
from Crypto.Cipher import AES
import base64
import ssl
class RemoteClient:
def __init__(self, host='127.0.0.1', port=5000):
config = configparser.ConfigParser()
config.read('config.ini')
self.host = config['Server']['host']
self.port = int(config['Server']['port'])
self.client_id = config['Authentication']['client_id']
# 初始化加密组件
self.cipher = AES.new(
base64.b64decode(config['Security']['encryption_key']),
AES.MODE_CBC,
base64.b64decode(config['Security']['encryption_salt'])
)
# 创建SSL上下文
self.context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
self.context.load_cert_chain(config['Authentication']['cert_file'])
self.context.check_hostname = False
self.sock = self.context.wrap_socket(
socket.socket(socket.AF_INET, socket.SOCK_STREAM),
server_hostname=config['Server']['host']
)
self.prev_hash = None
self.prev_mouse = (0, 0)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
logger.add('remote_client.log',
rotation='10 MB',
retention='7 days',
format='{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function} - {message}')
def connect(self):
try:
self.sock.connect((self.host, self.port))
logger.info(f'成功连接到服务器 {self.host}:{self.port}')
except Exception as e:
logger.error(f'连接错误: {e}')
def capture_screen(self):
with mss.mss() as sct:
screenshot = sct.grab(sct.monitors[0])
raw_bytes = mss.tools.to_png(sct.grab(sct.monitors[0]), (0, 0, screenshot.width, screenshot.height))
current_hash = zlib.crc32(raw_bytes)
if current_hash != self.prev_hash:
original_size = len(raw_bytes)
compressed = zlib.compress(raw_bytes, level=9)
compressed_size = len(compressed)
ratio = (1 - compressed_size/original_size) * 100
logger.debug(f'屏幕变化检测 [尺寸: ({screenshot.width},{screenshot.height})] [压缩率: {ratio:.1f}%]')
self.prev_hash = current_hash
return ('screen', compressed, (screenshot.width, screenshot.height))
return None
def get_mouse_data(self):
x, y = pyautogui.position()
buttons = pyautogui.mouseDown()
if (x, y) != self.prev_mouse or buttons:
logger.info(f'鼠标事件 [坐标: ({x},{y})] [按键: {buttons}]')
data = struct.pack('!II?', x, y, buttons)
self.prev_mouse = (x, y)
return ('mouse', data)
return None
def send_data(self, data_type, payload, size=None):
header = struct.pack('!4sI', data_type.encode(), len(payload))
if size:
header += struct.pack('!II', *size)
try:
self.sock.sendall(header + payload)
logger.trace(f'发送{data_type}数据 [大小: {len(payload)}字节]')
except Exception as e:
logger.warning(f'发送错误: {e}')
self.connect()
def run(self):
self.connect()
while True:
start_time = time.time()
# 捕获屏幕差异
screen_data = self.capture_screen()
if screen_data:
self.send_data(*screen_data)
# 捕获鼠标状态
mouse_data = self.get_mouse_data()
if mouse_data:
self.send_data(*mouse_data)
# 保持2秒间隔
elapsed = time.time() - start_time
if elapsed < 2:
time.sleep(2 - elapsed)
if __name__ == '__main__':
client = RemoteClient()
client.run()