Files
workphone-sdk/sdk/app/services/server_frida_bridge.py

97 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""宝塔侧 Frida RPC 桥。
手机通过认证的反向隧道暴露 frida-serverSDK 容器在本模块中持有真正的
Frida Session 和 JS RPC。Android 系统控制仍走手机 WebSocket两条通道互不抢占。
"""
from __future__ import annotations
import asyncio
import logging
import threading
from typing import Any, Dict
logger = logging.getLogger(__name__)
class ServerFridaBridge:
def __init__(self) -> None:
self._manager = None
self._executor = None
self._lock = threading.RLock()
@staticmethod
def _settings():
from config import settings
return settings
def enabled_for(self, device_id: str) -> bool:
settings = self._settings()
if not bool(getattr(settings, "SERVER_FRIDA_ENABLED", False)):
return False
expected = str(getattr(settings, "SERVER_FRIDA_DEVICE_ID", "") or "").strip()
return not expected or expected == device_id
def _connect(self) -> bool:
with self._lock:
if self._manager and getattr(self._manager, "connected", False):
return True
from hook.frida_manager import FridaManager
from hook.hook_executor import HookExecutor
settings = self._settings()
manager = FridaManager(
mode="remote",
gadget_host=str(getattr(settings, "SERVER_FRIDA_HOST", "172.18.0.1")),
gadget_port=int(getattr(settings, "SERVER_FRIDA_PORT", 14538)),
use_adb_forward=False,
auto_reconnect=True,
)
if not manager.start():
logger.warning("宝塔 Frida 桥连接失败")
return False
self._manager = manager
self._executor = HookExecutor(manager)
logger.info("宝塔 Frida 桥已附着微信并加载 RPC")
return True
def execute_sync(self, action: str, params: Dict[str, Any]) -> Dict[str, Any]:
try:
if not self._connect():
return {
"success": False,
"code": 503,
"error": "宝塔 Frida 桥不可用,请检查手机反向隧道和微信进程",
"_channel_used": "server/frida/offline",
}
result = self._executor.execute(action, params)
result.setdefault("code", 200 if result.get("success") else 500)
result["_channel_used"] = "server/frida"
result["transport"] = "frida_reverse_tunnel"
return result
except Exception as exc:
logger.exception("宝塔 Frida RPC 执行异常")
return {
"success": False,
"code": 500,
"error": str(exc),
"_channel_used": "server/frida/error",
}
async def execute(self, device_id: str, action: str, params: Dict[str, Any]) -> Dict[str, Any]:
if not self.enabled_for(device_id):
return {"success": False, "code": 503, "error": "宝塔 Frida 桥未启用"}
return await asyncio.to_thread(self.execute_sync, action, params)
def status(self) -> Dict[str, Any]:
connected = bool(self._manager and getattr(self._manager, "connected", False))
return {
"enabled": bool(getattr(self._settings(), "SERVER_FRIDA_ENABLED", False)),
"connected": connected,
"manager": self._manager.get_status() if connected else None,
}
server_frida_bridge = ServerFridaBridge()