#!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # 工作手机 · 无 USB 无线主控一键脚本(WiFi adb + 设备本机 stealth Frida + WS Agent) # # 解决:USB 线材/接口物理不稳反复掉线。改用 WiFi adb 传输,u2/frida 全走无线; # WS 身份仍用逻辑 device_id(SDK/hub 设备身份不变)。 # # 真源:开发文档/10、项目管理/工作日志.md 2026-05-31 15:58 · 真机铁律 §〇.八 无线主控 # # 用法: # bash wireless_master_oneclick.sh [USB_SERIAL] [SDK_HOST:PORT] [WIFI_PORT] # - USB_SERIAL : 首次开 tcpip 用的 USB 序列(默认 xgfe65eimrrofyws) # - SDK_HOST : SDK 地址(默认 127.0.0.1:8899) # - WIFI_PORT : adb tcpip 端口(默认 5555) # # 前置:设备已 Root、已装 frida(phantom_frida_config.json 指向 stealth 二进制), # Mac 与设备同一 WiFi。USB 仅首次开 tcpip 时短暂连接,之后可拔线。 # ───────────────────────────────────────────────────────────────────────────── set -uo pipefail USB_SERIAL="${1:-xgfe65eimrrofyws}" SDK_HOST="${2:-127.0.0.1:8899}" WIFI_PORT="${3:-5555}" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" AGENT_DIR="$(cd "${SCRIPT_DIR}/../agent" && pwd)" PHANTOM_CFG="${SCRIPT_DIR}/anti_detect/phantom_frida_config.json" DEVICE_ID="${USB_SERIAL}" # 逻辑 device_id(WS 身份),全程不变 export ANDROID_ADB_SERVER_PORT="${ANDROID_ADB_SERVER_PORT:-5038}" adb() { command adb -P "${ANDROID_ADB_SERVER_PORT}" "$@" } log(){ echo "[$(date +%H:%M:%S)] $*"; } fatal(){ echo "[FATAL] $*" >&2; exit 1; } # ── 1. 经 USB 开 tcpip 并取设备 WiFi IP ────────────────────────────────────── log "① 经 USB(${USB_SERIAL}) 开启 adb tcpip ${WIFI_PORT} 并取 WiFi IP" WIFI_IP="$(adb -s "${USB_SERIAL}" shell ip route 2>/dev/null | grep -oE 'src [0-9.]+' | awk '{print $2}' | head -1)" if [[ -z "${WIFI_IP}" ]]; then # 设备可能已是 WiFi adb,尝试从已连接条目取 WIFI_IP="$(adb devices | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:'"${WIFI_PORT}"'' | head -1 | cut -d: -f1)" fi [[ -n "${WIFI_IP}" ]] || fatal "无法获取设备 WiFi IP(确认设备已连 WiFi 且 USB 可见,或已 adb connect)" log " 设备 WiFi IP=${WIFI_IP}" adb -s "${USB_SERIAL}" tcpip "${WIFI_PORT}" >/dev/null 2>&1 || true sleep 3 # ── 2. adb connect WiFi + 稳定性校验 ──────────────────────────────────────── WIFI_SERIAL="${WIFI_IP}:${WIFI_PORT}" log "② adb connect ${WIFI_SERIAL}" adb connect "${WIFI_SERIAL}" >/dev/null 2>&1 sleep 2 OK=0 for i in 1 2 3 4; do [[ "$(adb -s "${WIFI_SERIAL}" shell echo ok 2>/dev/null | tr -d '\r')" == "ok" ]] && OK=$((OK+1)) sleep 1 done log " WiFi adb 稳定 ${OK}/4" [[ "${OK}" -ge 3 ]] || fatal "WiFi adb 不稳定(${OK}/4),请检查同网/路由" # ── 3. 启动设备本机 stealth frida-server(按 phantom 配置端口/二进制)────────── FRIDA_PORT="$(python3 -c "import json;print(json.load(open('${PHANTOM_CFG}'))['listen_port'])" 2>/dev/null || echo 27042)" FRIDA_BIN="$(python3 -c "import json;print(json.load(open('${PHANTOM_CFG}'))['binary_path'])" 2>/dev/null || echo /data/local/tmp/frida-server-16)" FRIDA_BASE="$(basename "${FRIDA_BIN}")" log "③ 重启本机 stealth frida ${FRIDA_BIN} @ ${FRIDA_PORT}(setsid 脱离会话)" adb -s "${WIFI_SERIAL}" shell "su -c 'pkill -f ${FRIDA_BASE} 2>/dev/null; pkill -f frida-server 2>/dev/null; true'" >/dev/null 2>&1 || true sleep 1 adb -s "${WIFI_SERIAL}" shell "su -c 'setsid ${FRIDA_BIN} -l 0.0.0.0:${FRIDA_PORT} /dev/null 2>&1 &'" >/dev/null 2>&1 sleep 4 adb -s "${WIFI_SERIAL}" shell "su -c 'ps -A | grep ${FRIDA_BASE}'" 2>/dev/null | head -1 \ || fatal "frida 进程未确认" adb -s "${WIFI_SERIAL}" forward "tcp:${FRIDA_PORT}" "tcp:${FRIDA_PORT}" >/dev/null # ── 4. 确保微信运行(温和 am start,不 frida-spawn)───────────────────────── if [[ -z "$(adb -s "${WIFI_SERIAL}" shell pidof com.tencent.mm 2>/dev/null | tr -d '\r')" ]]; then log "④ 拉起微信(am start,禁 frida-spawn)" adb -s "${WIFI_SERIAL}" shell am start -n com.tencent.mm/.ui.LauncherUI >/dev/null 2>&1 || true sleep 5 fi # ── 5. 启动 Agent(WP_DEVICE_SERIAL=WiFi 序列,device_id=逻辑身份)─────────── log "⑤ 启动 Agent:device_id=${DEVICE_ID}(WS身份) / adb_serial=${WIFI_SERIAL}(u2/frida传输)" pkill -f "agent.py -d ${DEVICE_ID}" 2>/dev/null || true sleep 2 WIRELESS_LOG="${SCRIPT_DIR}/../logs/wireless_agent.log" : > "${WIRELESS_LOG}" AGENT_PID="$( cd "${AGENT_DIR}" export WP_DEVICE_SERIAL="${WIFI_SERIAL}" export WP_FRIDA_MODE=remote export WP_FRIDA_PORT="${FRIDA_PORT}" export WORKPHONE_AGENT_LOG="${WIRELESS_LOG}" export WORKPHONE_WS_URL="ws://${SDK_HOST}/ws/device" export WORKPHONE_DEVICE_ID="${DEVICE_ID}" python3 - <<'PY' import os import subprocess import sys cmd = [ sys.executable, "agent.py", "-d", os.environ["WORKPHONE_DEVICE_ID"], "-s", os.environ["WORKPHONE_WS_URL"], "--heartbeat", "10", ] with open(os.environ["WORKPHONE_AGENT_LOG"], "ab", buffering=0) as log: proc = subprocess.Popen( cmd, cwd=os.getcwd(), env=os.environ.copy(), stdin=subprocess.DEVNULL, stdout=log, stderr=subprocess.STDOUT, start_new_session=True, close_fds=True, ) print(proc.pid) PY )" echo "${AGENT_PID}" > "${SCRIPT_DIR}/../logs/wireless_agent.pid" log " Agent pid=${AGENT_PID}(日志 ${WIRELESS_LOG})" for _i in $(seq 1 45); do if ! kill -0 "${AGENT_PID}" 2>/dev/null; then tail -80 "${WIRELESS_LOG}" >&2 || true fatal "Agent 启动后退出" fi if grep -q "RPC ping: pong" "${WIRELESS_LOG}" 2>/dev/null && \ grep -q "服务器确认注册" "${WIRELESS_LOG}" 2>/dev/null; then log " Agent WS + Frida RPC 已就绪" break fi sleep 2 done # ── 6. 验证无线 Hook 链路 ─────────────────────────────────────────────────── log "⑥ 验证无线 Hook(get_profile)" RESP="$(curl -s -m 45 -X POST "http://${SDK_HOST}/api/v3/hook/execute" \ -H 'Content-Type: application/json' \ -d "{\"device_id\":\"${DEVICE_ID}\",\"platform\":\"wechat\",\"action\":\"get_profile\",\"params\":{},\"hook_only\":true}")" echo "${RESP}" | head -c 300; echo OK="$(echo "${RESP}" | python3 -c 'import json,sys try: d=json.load(sys.stdin) print(bool((d.get("data") or {}).get("success") or d.get("success"))) except Exception: print(False)' 2>/dev/null || echo False)" CH="$(echo "${RESP}" | python3 -c 'import json,sys try: d=json.load(sys.stdin) print(d.get("channel_used") or (d.get("data") or {}).get("channel") or "") except Exception: print("")' 2>/dev/null || true)" if [[ "${OK}" == "True" ]] && echo "${CH}" | grep -Eqi 'frida|hook'; then log "✅ 无 USB 无线主控就绪:WiFi adb + 本机 stealth frida + WS + Hook" log " 现在可拔掉 USB 线,控制/取材料经 WiFi 无线进行。" else tail -80 "${WIRELESS_LOG}" >&2 || true fatal "Hook 未确认成功(frida attach / 微信运行 / 端口转发)" fi log "USB 掉线无影响;如换网/IP 变化,重跑本脚本即可。"