mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 17:10:43 +00:00
琚帶绔?- 淇 MTU 闂锛氬す MSS + 璺緞 MTU 鎺㈡祴锛堝叕缃戝彲鐢ㄧ巼 48% -> 100%锛?- 澶嶇敤 HTTP 杩炴帴锛堝厤鎺夋瘡娆℃柊寤?TLS 鐨?30% 鎻℃墜澶辫触锛?- 姣忓垎閽熷洖澶存壘灞€鍩熺綉锛岃嚜鍔ㄥ垏鍥炲揩 400 鍊嶇殑璺緞 - 鐢婚潰蹇冭烦甯э細闈欐鏃剁渷娴侀噺锛屽鎴风浠嶇煡閬撴祦鏄椿鐨?- 閿佸睆鏃剁粰鍑哄彲鎿嶄綔鐨勬彁绀? 鎵嬭〃绔?- 鍐呯疆 GTS Root R4 / GlobalSign Root CA锛屼慨 SSLHandshakeException - 杩炴帴閿欒缈昏瘧鎴愪汉璇濓紙璇佷功/鏃堕棿/瑙f瀽/瓒呮椂鍒嗗埆鎻愮ず锛?- 缁忎腑杞繛涓婂悗鐢ㄦ湇鍔″櫒鎶ョ殑鍦板潃鍒锋柊宸查厤瀵硅褰?- 鏂板灞€鍩熺綉杩炴帴椤甸潰銆佹湇鍔″櫒寤惰繜妫€娴? 鏈嶅姟鍣ㄧ - 鏀寔 chunked 璇锋眰浣擄紙淇瘡 16 绉掍竴娆$殑杩炴帴閿欎贡涓庡ぇ闈㈢Н 502锛?- 缃戠粶璋冧紭鑴氭湰 net-tune.sh锛堝紑鏈鸿嚜鍔ㄥ簲鐢級 - 绠$悊椤碉細鎵归噺鍒犻櫎銆佺綉缁滀綋妫€銆佷笅杞藉尯 - 闅ч亾鏀?HTTP/2 + 鍙岃繛鎺? 鏂囨。 - 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
656 lines
31 KiB
Markdown
656 lines
31 KiB
Markdown
# 局域网遥控 · LAN Remote
|
||
|
||
用手表(安卓)遥控自己的电脑。同一个 WiFi 下即可,不经过任何服务器。
|
||
|
||
```
|
||
┌─────────────────┐ 局域网 TCP ┌──────────────────┐
|
||
│ 手表控制端 APK │ ─────────────────────────► │ Windows 被控端 │
|
||
│ 490×602 大按钮 │ ◄───────────────────────── │ 可见托盘 + 配对码 │
|
||
└─────────────────┘ └──────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 一、先说清楚这个工具「不是什么」
|
||
|
||
你最初的描述里,有几条我**明确没有做**,因为它们属于恶意软件特征:
|
||
|
||
| 你提的要求 | 为什么不做 |
|
||
|---|---|
|
||
| 注册成系统更新组件、**杀毒软件杀不掉** | 这是免杀对抗。正常远控工具(TeamViewer、向日葵、AnyDesk)从不做这个。 |
|
||
| 托盘不显示、**任务管理器里看不到** | 这是对电脑使用者隐藏自身。 |
|
||
| 伪装成普通系统文件常驻 | 持久化 + 伪装。 |
|
||
|
||
**原因很简单**:如果被控的是你自己的电脑,你不需要隐藏——你会希望它可见、能管理、能一键断开。而"杀软杀不掉、任务管理器看不到"只在一种场景下有意义:**用电脑的人不知道你在控制它**。
|
||
|
||
所以这一版是:**被控端全程可见、可随时断开、权限可随时关闭**。它是个正经工具,不是木马。
|
||
|
||
---
|
||
|
||
## 二、快速开始(3 步)
|
||
|
||
### 第 1 步:电脑端
|
||
|
||
把 `LanRemote-Agent-Windows.zip` 解压到任意目录,双击 `LanRemote-Agent.exe`。
|
||
|
||
程序会弹出窗口,**窗口中间有一组 6 位配对码**,例如:
|
||
|
||
```
|
||
在手表上输入这组配对码
|
||
4 5 4 5 3 4
|
||
```
|
||
|
||
窗口里同时能看到:
|
||
- 当前连接状态
|
||
- 防火墙是否放行(没放行会显示橙色提示 + 「一键修复」按钮)
|
||
- 「打开接收目录」「退出」
|
||
|
||
**关掉窗口 = 程序继续在后台跑**(没有托盘图标)。
|
||
想再打开窗口,**再双击一次 EXE** 就行,不会重复起进程。
|
||
想彻底退出,在窗口上点「退出」。
|
||
|
||
### 第 2 步:手表端
|
||
|
||
安装 `LanRemote-Watch-1.3.0.apk`,打开后点那个大按钮 **「自动搜索电脑」**。
|
||
|
||
App 会往局域网广播一个探测包,被控端收到后回自己的名字和端口,
|
||
**所以手表端不用输 IP、不用管网段、也不用管电脑上装了几个虚拟网卡**。
|
||
|
||
搜到之后点一下那台电脑,输入被控端窗口上的 6 位数字,就连上了。
|
||
|
||
### 第 3 步:之后就不用再输了
|
||
|
||
配对成功后令牌保存在手表上,**下次打开 App 会自动搜到并直接连**,
|
||
连数字都不用再输。
|
||
|
||
多台电脑就配对多次,列表里点哪个连哪个。长按可以删除配对。
|
||
|
||
> 如果搜不到,展开「手动输入地址」可以自己填 IP 和端口 —— 但绝大多数情况
|
||
> 下搜不到都不是 IP 的问题,而是**防火墙没放行**(见下面第五节)。
|
||
|
||
---
|
||
|
||
### 工具箱(唯一入口)
|
||
|
||
被控端目录里有个 **`工具箱.bat`**,双击它就能看到所有功能:
|
||
|
||
```
|
||
============================================================
|
||
局域网遥控 . 工具箱 版本 1.3.0
|
||
============================================================
|
||
|
||
1. 启动被控端 日常使用就点这个
|
||
2. 一键修复防火墙 连不上时先试这个(需要管理员)
|
||
3. 网络自检 还连不上就用它排查
|
||
4. 查看使用说明
|
||
5. 查看运行日志
|
||
6. 打开接收文件夹
|
||
7. 查看当前防火墙状态
|
||
|
||
0. 退出
|
||
```
|
||
|
||
排查连接问题的推荐顺序:**1 → 2 → 3**。
|
||
|
||
| 选项 | 作用 |
|
||
|---|---|
|
||
| **1 启动被控端** | 确认程序在跑(任务管理器里能看到 `LanRemote-Agent.exe`) |
|
||
| **2 一键修复防火墙** | 弹一次 UAC 点「是」。删掉「阻止」规则 + 补一条**程序级**放行规则。后者才是治本 |
|
||
| **3 网络自检** | 跑起来后到手表上点「测一下」,看电脑窗口有没有 `>>> 收到 TCP 连接 <<<` |
|
||
| **7 查看防火墙状态** | 随时确认四条规则在不在、有没有阻止规则 |
|
||
|
||
网络自检的两种结果:
|
||
|
||
- **收到连接** → 包能到电脑,问题在本机(程序没跑 / 端口被占)
|
||
- **一个包都没收到** → 包没到,多半是路由器开了「AP 隔离」
|
||
|
||
---
|
||
|
||
## 三、功能
|
||
|
||
手表上全部是 58~64dp 的大按钮,两列排布,整页可滚动。
|
||
|
||
| 分类 | 功能 |
|
||
|---|---|
|
||
| **媒体** | 播放/暂停、停止、上一曲、下一曲、音量±、静音 |
|
||
| **显示** | 投图到电脑(全屏显示,按 Esc 或点一下关闭) |
|
||
| **屏幕** | **实时屏幕镜像**(默认 4 fps,可调帧率/画质/分辨率)、**一键截屏**并保存到手表 |
|
||
| **音频** | 放音到电脑(用系统 MCI 播放,不弹播放器窗口) |
|
||
| **文件** | 发送文件到电脑 / 接收电脑上的文件 |
|
||
| **剪贴板** | 手表文字 → 电脑剪贴板;电脑剪贴板 → 手表(自动复制) |
|
||
| **语音** | 让电脑语音播报指定文字(系统自带 TTS) |
|
||
| **通知** | 在电脑托盘弹通知 |
|
||
| **电源** | 关机、重启、锁屏、睡眠、取消关机(二次确认) |
|
||
| **其他** | 自定义命令(回显输出和退出码)、查看电脑系统信息 |
|
||
| **被动** | 电脑上复制东西时,手表会收到推送提示 |
|
||
|
||
---
|
||
|
||
## 四、安全设计
|
||
|
||
这是重点,请看完。
|
||
|
||
1. **首次连接必须配对**:电脑端生成 6 位随机码,只在窗口上显示,手表输入正确才能连。
|
||
2. **令牌制**:配对成功后发一个 32 位随机令牌,之后靠令牌免配对码登录。
|
||
3. **未鉴权拒绝一切命令**:没通过握手就发命令,服务端直接拒绝。
|
||
4. **权限开关实时生效**:窗口上可以随时关掉"自定义命令"、"电源操作"、"屏幕镜像",关掉后远程立刻执行不了。
|
||
5. **无托盘但仍有可见性**:按需求去掉了托盘图标;只要有设备连着,
|
||
屏幕右上角就会出现一条「已连接」提示条,可一键断开。
|
||
6. **屏幕共享有强制提示**(见下)。
|
||
7. **不写注册表**:所有数据放在程序目录下的 `data/`,绿色便携。
|
||
8. **只在局域网**:不联外网、不上传任何数据。想更安全就在防火墙里只放行内网段。
|
||
|
||
### 屏幕镜像的强制可见提示
|
||
|
||
只要有人在看你的屏幕,被控端**屏幕右上角就会出现一条红色提示条**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ ● 屏幕正在被共享 1 台设备正在观看 · 4.0 fps [停止共享] │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
这条提示的规则:
|
||
|
||
- **一定有**:开始推流就出现,没有开关能关掉它。界面里也没有"隐藏提示"这类选项。
|
||
- **本机可一键掐断**:点提示条上的「停止共享」,立刻断开所有观看,并通知手表。
|
||
- **截屏也会闪一下**:单次截屏虽然短暂,同样会闪 2.5 秒提示。
|
||
- **无人观看自动停**:所有手表都断开后,抓屏线程立即结束,提示条消失,不留后台耗电。
|
||
- **关掉权限立刻断**:把窗口上的「允许屏幕镜像 / 截屏」取消勾选,正在进行的共享立刻被掐断。
|
||
|
||
这是本工具和"屏幕监视软件"的分界线:**被控端永远知道、永远能停。**
|
||
|
||
> ⚠️ 自定义命令 = 远程执行任意命令。这是你自己电脑上你自己开的功能,
|
||
> 但请务必:**只在你信任的局域网里用**,用完可以在窗口里关掉它。
|
||
|
||
### 安卓端权限
|
||
|
||
手表 App **在第一次启动时一次性把需要的权限全要了**,之后选图片、选音频、发文件都不再弹窗:
|
||
|
||
| 权限 | 用途 |
|
||
|---|---|
|
||
| `INTERNET` / `ACCESS_NETWORK_STATE` / `ACCESS_WIFI_STATE` | 连局域网 |
|
||
| `READ_MEDIA_IMAGES` / `READ_MEDIA_AUDIO` / `READ_MEDIA_VIDEO`(Android 13+) | 列出手表上的媒体文件 |
|
||
| `READ_EXTERNAL_STORAGE`(Android 12 及以下,`maxSdkVersion=32`) | 同上 |
|
||
|
||
有权限时用**内置选择器**(带缩略图,直接在 App 里列文件);万一权限被拒,会自动回退到系统选择器,
|
||
所以功能不会因为拒权限而不可用。
|
||
|
||
---
|
||
|
||
## 五、连不上?先看这里
|
||
|
||
**实测中「连不上」最常见的原因只有一个:Windows 防火墙没放行。**
|
||
|
||
家用 WiFi 一般会被 Windows 归类成「公用网络(Public)」,
|
||
而公用网络的默认入站动作是**阻止**。如果没有显式放行规则,
|
||
手表的连接会被**静默丢包** —— 表现就是「配对码明明对,但一直转圈连不上」。
|
||
|
||
真机上验证过:
|
||
|
||
```
|
||
Get-NetFirewallRule -Direction Inbound -Action Allow -> 0 条规则
|
||
Get-NetConnectionProfile -InterfaceAlias WLAN -> Public
|
||
```
|
||
|
||
**解决办法**:被控端窗口会自动检测并显示一条橙色提示
|
||
|
||
```
|
||
防火墙未放行,手表连不上。 [一键修复]
|
||
```
|
||
|
||
点「一键修复」,同意一次管理员请求即可(放行需要管理员权限,这一步躲不掉)。
|
||
程序也会在目录下生成 `放行防火墙.bat`,可以右键「以管理员身份运行」。
|
||
|
||
手动执行等价于:
|
||
|
||
```powershell
|
||
netsh advfirewall firewall add rule name="LAN Remote TCP" dir=in action=allow protocol=TCP localport=8765 profile=any
|
||
netsh advfirewall firewall add rule name="LAN Remote UDP" dir=in action=allow protocol=UDP localport=8766 profile=any
|
||
```
|
||
|
||
**如果防火墙已放行还是连不上**,依次检查:
|
||
|
||
1. 手表和电脑是不是**同一个 WiFi**(不是手机热点、不是客人网络)
|
||
2. 路由器有没有开 **「AP 隔离」**(开了的话同一 WiFi 的设备也互相不通)
|
||
3. 电脑上是不是有 VPN / 加速器 / 虚拟网卡在抢占路由
|
||
(程序会优先选真实网卡地址;本机装 Tailscale 时 `hostname` 会解析到
|
||
169.254 链路地址,程序已按网段优先级排除了这种情况)
|
||
4. 端口被别的程序占用(程序会提示「端口被占用」)
|
||
|
||
---
|
||
|
||
## 六、连不上时:用「设备诊断」
|
||
|
||
**诊断已经合并进手表主程序了**,不需要再装单独的 App。
|
||
|
||
手表上:**主界面 ->「设备诊断」** -> 自动开始检测。
|
||
|
||
它会自动:
|
||
|
||
1. **采集环境信息** —— 厂商/型号/安卓版本/API、屏幕像素与 density、
|
||
屏幕 dp 尺寸、字体缩放、是否被识别为手表、各权限的授予状态
|
||
2. **采集网络参数** —— 连接类型、WiFi 名称/信号、本机所有 IPv4 地址与
|
||
前缀长度、DHCP 网关/掩码/DNS
|
||
3. **真的跑一次局域网自动发现**(UDP 广播 4 秒),列出找到的电脑
|
||
4. **对找到的每台电脑做真实 TCP 连接测试**,报告成功/失败与耗时
|
||
5. 测完**自动复制到剪贴板**,直接到聊天窗口粘贴发给开发者即可
|
||
|
||
如果一台都没搜到,可以在诊断界面手动填电脑 IP 点「测一下」——
|
||
它会分别做 **UDP 单播探测** 和 **TCP 连接**,能直接区分问题在哪:
|
||
|
||
| 结果 | 说明 |
|
||
|---|---|
|
||
| 单播有应答 + TCP 成功 | 网络是通的,问题在广播(路由器多播过滤 / AP 隔离) |
|
||
| 单播有应答 + TCP 失败 | 广播被拦,且**电脑防火墙拦了 TCP 8765** → 点被控端的「一键修复」 |
|
||
| 单播无应答 + TCP 失败 | 根本没通(不同网段 / 电脑没运行 / 防火墙全拦) |
|
||
|
||
**它刻意不收集什么:**
|
||
|
||
- IMEI、序列号、手机号、运营商
|
||
- 联系人、短信、通话记录
|
||
- 相册、文件列表、剪贴板内容
|
||
- 位置坐标(定位权限只用于读取 WiFi 名称,不读经纬度)
|
||
- 账号、已安装应用列表
|
||
|
||
报告内容全部显示在屏幕上,复制由使用者主动触发。
|
||
|
||
诊断与主程序在**同一个 APK** 里,共用同一份自动发现实现
|
||
(`DiscoveryCore`),所以不会出现「诊断说能通、主程序连不上」的假象。
|
||
|
||
底部还有一行「手动测电脑 IP」+「测一下」按钮——广播被拦时,
|
||
它会分别做 UDP 单播和 TCP 连接,直接告诉你问题在哪一段。
|
||
|
||
---
|
||
|
||
## 六点五、电脑端全部图形化(不依赖任何 .bat)
|
||
|
||
被控端窗口底部一行短按钮:
|
||
|
||
```
|
||
[ 接收 ] [ 自检 ] [ 说明 ] [ 设置 ] [ 退出 ]
|
||
```
|
||
|
||
| 按钮 | 作用 |
|
||
|---|---|
|
||
| **接收** | 打开收到的文件目录 |
|
||
| **自检** | 图形化网络自检(见下) |
|
||
| **说明** | 窗口里直接看使用说明 |
|
||
| **设置** | 投图标题 / 播报音色 / 语速 / 音乐目录 |
|
||
| **退出** | 真正结束进程并释放端口 |
|
||
|
||
### 图形化自检
|
||
|
||
**不再需要点任何 .bat。** 自检直接读被控端自己的计数器,
|
||
所以被控端在跑的时候也能诊断(旧的控制台版本要抢端口,跑不了):
|
||
|
||
```
|
||
● 正常 一切正常,手表应该能连上。
|
||
|
||
--- 本机网络 ---
|
||
192.168.2.64 [默认路由]
|
||
>>> 手表上填这个 IP:192.168.2.64
|
||
WiFi: 1602
|
||
|
||
--- 监听 ---
|
||
控制端口 TCP 8765: 监听中
|
||
发现端口 UDP 8766: 监听中
|
||
|
||
--- 收到过多少(关键)---
|
||
自动发现请求: 12 个
|
||
自检请求: 1 个
|
||
TCP 连接: 3 次
|
||
有数字说明手表的包能到达这台电脑
|
||
|
||
--- 防火墙 ---
|
||
端口放行 TCP: 是
|
||
程序级放行: 是 (LanRemote-Agent.exe)
|
||
阻止规则: 0 条(针对本程序)
|
||
|
||
--- 结论 ---
|
||
[OK] 一切正常,手表应该能连上。
|
||
```
|
||
|
||
窗口里还有「复制」和「一键修复防火墙」按钮。
|
||
|
||
**手表上点「连不上?」**,这台电脑会自动把自检窗口弹出来
|
||
(走 UDP,所以 TCP 被防火墙拦掉时也能到达)。
|
||
|
||
---
|
||
|
||
## 六点六、手表端:分页 + 37 个功能
|
||
|
||
**连接后**的界面是 6 个分页标签,每页最多 7 个按钮 —— 一屏放得下,**完全不用滚动**。
|
||
|
||
| 分页 | 功能 |
|
||
|---|---|
|
||
| **媒体** | 播放/暂停、停止、上一曲、下一曲、音量 +、音量 −、静音 |
|
||
| **屏幕** | 屏幕镜像、截屏、投图到电脑、放音到电脑、关显示器、设为壁纸 |
|
||
| **文件** | 发送文件、接收文件、剪贴板→电脑、取电脑剪贴板、剪贴板历史、打开文件夹 |
|
||
| **语音** | 语音播报、音色、朗读剪贴板、电脑音乐、弹通知 |
|
||
| **电脑** | 快捷命令、打开网址、进程管理、性能、磁盘、电量 |
|
||
| **系统** | 锁屏、睡眠、关机、重启、取消定时关机、定时关机、设备诊断 |
|
||
|
||
几个值得说的:
|
||
|
||
- **电脑音乐** —— 列出电脑音乐目录里的音频,选一个直接在电脑上播
|
||
- **音色** —— 列出电脑上所有 TTS 音色(中文 HuiHui / 英文 Zira 等),选一个
|
||
- **进程管理** —— 按内存排序列出电脑进程,可以结束
|
||
- **剪贴板历史** —— 电脑端保留最近 20 条剪贴板,手表上点一条就取回来
|
||
- **设为壁纸** —— 把刚投过去的那张图设成电脑桌面壁纸
|
||
- **快捷命令** —— 任务管理器 / 资源管理器 / CMD / 计算器 / 记事本 / 画图 / 控制面板 / 设备管理器
|
||
- **定时关机** —— 15 / 30 / 60 / 120 分钟后关机,可取消
|
||
|
||
**安全边界**(都有测试):
|
||
|
||
- 打开网址只允许 `http` / `https`,拒绝 `file://` 之类
|
||
- 播放本机音频只允许音乐目录内的文件
|
||
- 快捷命令和文件夹都是白名单,不接受任意路径
|
||
- 结束进程必须由用户在手表上确认
|
||
|
||
---
|
||
|
||
## 关于杀毒软件误报
|
||
|
||
### 先说结论
|
||
|
||
**这个工具没有做任何免杀。** 它会被某些杀软启发式报毒,这是真的,
|
||
我不打算靠混淆/加壳/加密去绕,因为那正是恶意软件的做法 ——
|
||
绕过去之后,你也分不清自己装的是不是真有毒。
|
||
|
||
真正能解决误报的路只有一条:**代码签名**(要买证书,见下)。
|
||
|
||
### 为什么会被盯上
|
||
|
||
| 特征 | 为什么杀软敏感 | 这是谁的需求 |
|
||
|---|---|---|
|
||
| PyInstaller 打包 | 打包器的引导代码是启发式的重灾区 | 你要「多文件 exe,双击就跑」 |
|
||
| 写注册表 Run 键 | 自启动是持久化的典型手法 | 你要「开机自启」 |
|
||
| 无窗口后台常驻 | 隐藏进程是木马的常见形态 | 你要「全程静默」 |
|
||
| 监听端口 + 收指令 | 远控和被控端在行为上无法区分 | 这就是远控工具 |
|
||
| 提权改防火墙 | 改防火墙规则经常被拦 | 你要「黑终端一闪修防火墙」 |
|
||
|
||
**这五条全是你明确要求的。** 它们组合在一起,行为特征上和远控木马是一回事 ——
|
||
区别在于:**配对码是你自己设的、认证是真的、你不会拿它去连别人的电脑。**
|
||
|
||
### 我做了哪些合法的降误报
|
||
|
||
1. **`--onedir` 而不是 `--onefile`**
|
||
onefile 每次启动都往临时目录解压自己,这是最容易被判毒的行为之一。
|
||
onedir 不解压,启动也更快。
|
||
|
||
2. **`--noupx`**
|
||
加壳压缩是杀软重点关注对象,明确关掉。
|
||
|
||
3. **完整的版本信息**
|
||
EXE 里写入了公司名、产品名、文件描述、版本、版权。
|
||
未签名二进制有正经的版本资源,比光秃秃的少一点可疑度,
|
||
也方便你在杀软里按「厂商 + 产品」加例外。
|
||
|
||
4. **不做任何偷偷摸摸的事**
|
||
没有自我复制、没有进程注入、没有内存加载、没有关闭杀软、
|
||
没有偷偷加防火墙例外。自启写注册表是**你勾了勾选框**才做的。
|
||
|
||
### 你遇到误报时怎么办
|
||
|
||
**优先做成例外,不要关杀软。**
|
||
|
||
被控端目录整个加进排除项即可(就是你放 `LanRemote-Agent.exe` 那个文件夹):
|
||
|
||
```
|
||
Windows 安全中心 → 病毒和威胁防护 → 管理设置
|
||
→ 排除项 → 添加或删除排除项 → 添加文件夹
|
||
→ 选 LanRemote-Agent 那个目录
|
||
```
|
||
|
||
加**文件夹**而不是单个 exe —— 因为 `_internal\` 里的 dll/pyd 也可能被单独报。
|
||
|
||
### 真正根治:代码签名
|
||
|
||
有了签名,SmartScreen 和大部分杀软就不会再拦。需要:
|
||
|
||
1. 买一张代码签名证书(OV 约 ¥1000-2000/年,EV 更贵但立刻获得 SmartScreen 信誉)
|
||
2. 用 `signtool` 给 `LanRemote-Agent.exe` 和 `_internal` 里的 dll 签名
|
||
3. 加时间戳(否则证书过期后签名失效)
|
||
|
||
买了证书之后告诉我,我把签名步骤加进构建脚本。
|
||
|
||
### 我查到的情况(本机)
|
||
|
||
这台机器上 Windows Defender 的**按需扫描是坏的**:
|
||
|
||
```
|
||
MpSmartConfigInitialize() failed (80070002)
|
||
```
|
||
|
||
Defender 的 PowerShell 模块(`Get-MpComputerStatus` 等)也不存在,
|
||
所以**我没法在这台机器上给你一个权威的"报不报毒"结论**。
|
||
我不会假装测过。
|
||
|
||
想自己确认的话,把 EXE 传到 VirusTotal 看一下 —— 那是最快的办法。
|
||
|
||
---
|
||
|
||
## 七、后台运行方式
|
||
|
||
按需求设计成**没有托盘图标**:
|
||
|
||
- 双击 EXE → 弹出一个小窗口,上面一串 6 位配对码
|
||
- **关掉窗口 → 程序继续在后台跑**,仍然占着 8765 / 8766 端口
|
||
- 任务管理器里能看到 `LanRemote-Agent.exe`
|
||
- **再双击一次 EXE → 把已经在跑的那个窗口叫回来**,不会重复起进程
|
||
(这里用 `SO_EXCLUSIVEADDRUSE`:Windows 上 `SO_REUSEADDR` 会允许
|
||
第二个进程绑同一端口,导致单实例判定失效 —— 实测踩到过)
|
||
- 想彻底退出:窗口上点「退出」
|
||
- 运行记录写在 `data\运行日志.txt`
|
||
|
||
**保留了一条可见性**:只要有设备连着,屏幕右上角会出现一条小提示条
|
||
(`● 已连接:<设备名>`,蓝色,带「断开」按钮);屏幕共享时它变红,
|
||
并带「停止共享」。没有托盘图标的前提下,这是让「有人正在控制这台电脑」
|
||
不被完全隐形的最低限度做法。空闲时它完全不显示。
|
||
|
||
---
|
||
|
||
## 八、常见问题
|
||
|
||
**Q:手表连不上?**
|
||
A:先看被控端窗口上有没有橙色「防火墙未放行」提示,有就点「一键修复」。
|
||
没有的话,装附带的「遥控诊断」跑一次,把结果发给开发者即可定位。
|
||
|
||
**Q:提示"电脑拒绝连接"?**
|
||
A:被控端程序没在运行(任务管理器里找 `LanRemote-Agent.exe`),或者端口被改了。
|
||
|
||
**Q:提示"配对码错误"?**
|
||
A:配对码会变——点了"换一组"或者被控端重启过,就用窗口上最新的那组。
|
||
|
||
**Q:下次打开还要输配对码?**
|
||
A:不该要。如果还要,说明上次配对没成功保存。
|
||
|
||
**Q:托盘图标在哪?**
|
||
A:按需求**没有托盘图标**。关窗后程序继续后台运行;再双击一次 EXE 就能找回窗口。
|
||
|
||
**Q:投图之后电脑上窗口关不掉?**
|
||
A:点一下图片,或者按 Esc。也可以把设置里的 `image_timeout` 改成秒数自动关闭。
|
||
|
||
**Q:手表屏幕显示不全?**
|
||
A:界面是按 490×602 自适应做的:宽度小于 200dp 时自动切成单列并加大按钮。
|
||
别的分辨率改 `MainActivity.java` 里 `adaptGridToScreen()` 的阈值即可。
|
||
|
||
---
|
||
|
||
## 九、项目结构
|
||
|
||
```
|
||
LanRemote/
|
||
├── windows/ # 被控端(Python)
|
||
│ ├── lanremote/
|
||
│ │ ├── protocol.py # 协议常量 + 分块编解码
|
||
│ │ ├── config.py # 数据持久化(设备令牌、设置)
|
||
│ │ ├── actions.py # 投图/放音/媒体/剪贴板/电源/命令/TTS
|
||
│ │ ├── screen.py # 屏幕捕获 + 帧流(Pillow,JPEG)
|
||
│ │ ├── discovery.py # UDP 广播应答(手表不用输 IP)
|
||
│ │ ├── firewall.py # 防火墙检测 + 一键提权放行
|
||
│ │ ├── instance.py # 单实例锁(再次双击找回窗口)
|
||
│ │ ├── server.py # TCP 服务 + 配对鉴权 + 命令分发 + 帧广播
|
||
│ │ └── ui.py # 小窗口 + 状态提示条(无托盘)
|
||
│ ├── run_agent.py # 启动入口
|
||
│ └── build_exe.ps1 # PyInstaller --onedir 打包
|
||
│
|
||
├── android/ # 手表控制端(纯 Java,无第三方依赖)
|
||
│ ├── src/com/lanremote/watch/
|
||
│ │ ├── Json.java # 自写 JSON(桌面 JVM 也能跑,便于联调)
|
||
│ │ ├── B64.java # 自写 Base64(兼容老 Android)
|
||
│ │ ├── RemoteClient.java # 协议客户端(纯 Java)
|
||
│ │ ├── DiscoveryCore.java # 自动发现核心(纯 Java,可桌面联调)
|
||
│ │ ├── Discovery.java # 安卓包装(MulticastLock)
|
||
│ │ ├── DeviceStore.java # 设备令牌持久化
|
||
│ │ ├── MediaPicker.java # 内置媒体选择器(免系统弹窗)
|
||
│ │ └── MainActivity.java # 490×602 自适应大按钮 + 镜像面板
|
||
│ ├── AndroidManifest.xml
|
||
│ ├── res/ # 图标 + 字符串
|
||
│ └── build_apk.ps1 # aapt2+javac+d8+apksigner 手工构建
|
||
│
|
||
├── diag/ # 早期独立诊断 App 的源码(已合并进主程序,不再单独出包)
|
||
│ ├── src/com/lanremote/diag/
|
||
│ │ └── DiagActivity.java # 环境采集 + 真实连通测试 + 一键复制
|
||
│ ├── AndroidManifest.xml
|
||
│ ├── res/ # 图标 + 字符串
|
||
│ └── build_diag_apk.ps1 # 复用主程序的 Json/DiscoveryCore 一起编译
|
||
│
|
||
├── _tests/ # 全部测试
|
||
│ ├── test_agent_protocol.py # 被控端协议回归(69 项)
|
||
│ ├── check_layout.py # 490×602 布局数学核算(22 项)
|
||
│ ├── test_indicator_visible.py# 屏幕共享强制提示(真实界面,9 项)
|
||
│ ├── test_simple_ui.py # 小窗口/无托盘/后台常驻(真实界面,12 项)
|
||
│ ├── java/JavaClientTest.java # 跨语言联调(48 项)
|
||
│ ├── run_stub_server.py # 无界面桩服务端
|
||
│ └── verify_all.ps1 # 一键全量验证(7 个阶段)
|
||
│
|
||
└── _build/ # 构建辅助
|
||
```
|
||
|
||
---
|
||
|
||
## 十、协议(想自己扩展可以看)
|
||
|
||
TCP 长连接,每条消息一行 UTF-8 JSON(`\n` 结尾),二进制用 Base64 分块(256KB/块)。
|
||
|
||
**握手**
|
||
|
||
| 方向 | 消息 |
|
||
|---|---|
|
||
| 手表→电脑 | `{"cmd":"pair","code":"454534","deviceId":"watch-xxx","deviceName":"Watch"}` |
|
||
| 电脑→手表 | `{"ok":true,"token":"<32位>","serverName":"DESKTOP-XXX"}` |
|
||
| 手表→电脑 | `{"cmd":"auth","deviceId":"...","token":"..."}` |
|
||
|
||
**命令**(需鉴权)
|
||
|
||
| cmd | 参数 | 说明 |
|
||
|---|---|---|
|
||
| `ping` | - | 心跳 |
|
||
| `info` | - | 系统信息 |
|
||
| `media` | `action` | playpause/stop/prev/next/volup/voldown/mute |
|
||
| `image` | `name,seq,last,data` | 投图(分块) |
|
||
| `audio` | `name,seq,last,data` | 放音(分块) |
|
||
| `clip_set` / `clip_get` | `text` / - | 剪贴板 |
|
||
| `say` | `text` | 语音播报 |
|
||
| `notify` | `title,text` | 通知 |
|
||
| `power` | `action` | shutdown/restart/lock/sleep/abort |
|
||
| `run` | `command` | 自定义命令 |
|
||
| `file_push` | `name,seq,last,data` | 上传文件 |
|
||
| `file_list` | - | 列出接收目录 |
|
||
| `file_pull` | `path` | 下载文件(分块回传) |
|
||
| `screen_start` | `fps,maxWidth,quality` | 开始实时屏幕镜像(1~15 fps) |
|
||
| `screen_stop` | - | 停止屏幕镜像 |
|
||
| `screenshot` | `maxWidth,quality` | 单次截屏,回包里直接带 JPEG(base64) |
|
||
|
||
**自动发现**(UDP 8766,让手表不用输 IP)
|
||
|
||
| 方向 | 报文 |
|
||
|---|---|
|
||
| 手表→广播 | `{"lanremote":"LANREMOTE_DISCOVER","proto":1}` |
|
||
| 电脑→单播 | `{"lanremote":"LANREMOTE_REPLY","proto":1,"name":"DESKTOP-X","port":8765,"version":"1.1.0"}` |
|
||
|
||
手表拿到回复后就知道电脑的 IP 和端口,直接连 TCP。与在哪个网段、
|
||
电脑有几张网卡都无关。
|
||
|
||
**事件推送**(电脑→手表,异步)
|
||
|
||
| event | 说明 |
|
||
|---|---|
|
||
| `clip` | 电脑剪贴板变化 |
|
||
| `file` | `file_pull` 的分块数据 |
|
||
| `frame` | 屏幕镜像的一帧(JPEG base64,带 `w`/`h`/`size`/`ts`) |
|
||
| `screen_stopped` | 被控端本机掐断了共享 |
|
||
| `status` | 状态消息 |
|
||
|
||
**注意三个容易踩的坑**(都是实测踩过的):
|
||
1. 分块上传时,**中间块不回包**,只在最后一块回一次。否则回复洪泛会导致后续命令消息错位。
|
||
2. `file_pull` 分块之后还会有一条最终回执,客户端必须读走,不然会污染下一条命令。
|
||
3. 镜像帧是**高频事件**,客户端读取线程必须把 `frame` 当事件异步处理,
|
||
绝不能让 `frame` 进入请求-应答队列,否则命令会全部超时。
|
||
|
||
---
|
||
|
||
## 十一、测试情况
|
||
|
||
跑 `_tests\verify_all.ps1` 一键全量验证:
|
||
|
||
| 项目 | 内容 | 结果 |
|
||
|---|---|---|
|
||
| Python 被控端协议回归 | 配对/鉴权/媒体/剪贴板/投图/放音/文件/命令/电源/屏幕镜像/截屏/多设备 | **69/69 PASS** |
|
||
| 手表布局适配核算 | 490×602 在 density 1.0~3.0 下的按钮尺寸与文字容量 | **22/22 PASS** |
|
||
| 屏幕共享强制提示 | 真实 tkinter 界面 + Win32 `EnumWindows` 枚举窗口 | **9/9 PASS** |
|
||
| 小窗口与后台常驻 | 真实界面 + Win32:窗口尺寸、关窗后进程存活、双启动找回窗口、无托盘 | **12/12 PASS** |
|
||
| Java 协议层编译 | javac 目标 Java 8 | **PASS** |
|
||
| Java ↔ 桩服务端 | 跨语言联调(含帧流、截屏、**UDP 自动发现**) | **48/48 PASS** |
|
||
| Java ↔ 打包后 EXE | 端到端跑真交付物 | **48/48 PASS** |
|
||
| 交付 zip 解压重跑 | 解压到全新目录后运行 EXE 再跑一遍 | **PASS** |
|
||
|
||
**测试中发现并修掉的真实 bug:**
|
||
|
||
1. **分块上传回复洪泛** —— 服务端给每个分块都回一次 ack,客户端只读一次,导致后续所有命令消息错位(`run` 收到的是 `file_pull` 的回包)。改为只在最后一块回包。
|
||
2. **同名文件拉回旧版本** —— 同名文件第二次上传会存成 `name_1.bin`,但 `file_pull("name.bin")` 会拉到**上一轮的旧文件**。改为按名字匹配取最新的一份。(靠三方 SHA-256 比对才定位出来:长度完全一致,只有内容不同。)
|
||
3. **损坏图片被当成成功** —— 实测发现传随机字节时 PIL 打开失败并返回错误;确认这是正确行为并加了回归用例。
|
||
4. **自定义命令的控制台噪音** —— `shutdown /a` 的报错会打到 stderr,改成全静默。
|
||
5. **镜像帧污染命令队列** —— 帧是高频事件,必须走事件通道;一旦混入请求-应答队列,所有命令都会超时。已在客户端读取线程里分流。
|
||
|
||
**屏幕相关的安全属性,是被单独验证过的:**
|
||
`_tests/test_indicator_visible.py` 启动**真实界面**(不是桩),开始共享后用 Win32 `EnumWindows`
|
||
在系统窗口列表里查找提示条,确认:开始共享时出现 → 停止后消失 → 再次共享再出现 →
|
||
客户端断开后自动消失。这条属性不靠"看代码相信",靠枚举窗口实证。
|
||
|
||
**未能验证的部分(如实说明):**
|
||
- **没有真机跑 APK**。这台机器上没接安卓设备,也没装模拟器。APK 的验证做到了:构建成功、签名校验通过、`aapt dump badging` 结构正确、dex 里类齐全、协议层在桌面 JVM 上连真实服务端 35/35 通过。**但界面在真实手表上的渲染效果没实测过。**
|
||
- 装到手表上如果布局有问题,改 `adaptGridToScreen()` 的阈值即可。
|
||
|
||
---
|
||
|
||
## 十二、自己重新构建
|
||
|
||
```powershell
|
||
# 被控端 → 多文件 EXE
|
||
powershell -ExecutionPolicy Bypass -File windows\build_exe.ps1
|
||
|
||
# 手表端 → APK
|
||
powershell -ExecutionPolicy Bypass -File android\build_apk.ps1
|
||
|
||
# 全量验证
|
||
powershell -ExecutionPolicy Bypass -File _tests\verify_all.ps1
|
||
```
|
||
|
||
APK 用的是工作区里现成的工具链(`starklink\toolchain`:JDK 17 + Android SDK 34 + build-tools 34),
|
||
走 `aapt2 → javac → d8 → zipalign → apksigner` 手工链,**不需要 Gradle**。
|
||
|
||
---
|
||
|
||
## 十三、法律与责任
|
||
|
||
本工具是**你自己的设备之间**的局域网遥控工具。
|
||
|
||
- 只用于你拥有或已获授权控制的电脑。
|
||
- 在他人电脑上安装并隐藏运行,属于违法行为(《刑法》285/286 条)。
|
||
- 本工具不提供任何隐藏、免杀、伪装能力,就是为了让它不能被用于那种场景。
|
||
|
||
请合法使用。
|