Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6d2706e2b | ||
|
|
a31a7d4d03 | ||
|
|
2f77fabd76 | ||
|
|
43abf4fe8c | ||
|
|
c71c22f7d1 | ||
|
|
970c0bad7d | ||
|
|
69983bfbf0 | ||
|
|
e419752a5c | ||
|
|
68598ed26d | ||
|
|
e7d33319c8 | ||
|
|
6a94b31be7 | ||
|
|
c7653cc698 | ||
|
|
02b58948a0 | ||
|
|
797004582f | ||
|
|
6e4a3b2464 | ||
|
|
c2f668b9db | ||
|
|
2940e15105 | ||
|
|
884d882eb7 | ||
|
|
b8bfac4641 | ||
|
|
4a64e54935 |
@@ -0,0 +1,4 @@
|
|||||||
|
.venv/
|
||||||
|
.deps_installed
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
@@ -1,162 +1,100 @@
|
|||||||
# First
|
# First
|
||||||
|
|
||||||
> 微信小程序调试工具 —— 基于 Frida + CDP 代理,支持 GUI 与 CLI 双模式
|
微信小程序安全调试工具 — Frida + CDP,支持 macOS / Windows
|
||||||
---
|
|
||||||
本项目仅支持windows,macos用户使用pd虚拟机即可
|
|
||||||
## 截图预览
|
|
||||||
|
|
||||||
### 主界面 / Control Panel
|
> 自v1.1.0版本后开始闭源,往后版本更新只上传编译好的版本,下载最新版请去release下载。
|
||||||
|
|
||||||

|
## 免责声明
|
||||||
|
|
||||||
### 路由导航
|
本工具仅供安全研究与学习使用,请勿用于未授权的目标,使用者须自行承担相关法律责任。
|
||||||

|
|
||||||
|
|
||||||
### 云函数分析
|
## 功能
|
||||||

|
|
||||||
|
|
||||||
### 调试开关(JSRPC 与调用 wx.cloud)
|
- Frida 注入微信,CDP 代理桥接 Chrome DevTools
|
||||||

|
- 云函数动态捕获(Hook wx.cloud.callFunction,参数修改重放)
|
||||||
|
- wx.* API 捕获(login / request / getUserProfile 等)
|
||||||
|
- 路由枚举与导航,跳转守卫检测
|
||||||
|
- wxapkg 解密解包 + 敏感信息扫描
|
||||||
|
- MCP Server 集成(AI 辅助分析)
|
||||||
|
- 偏移量 / Skills 在线更新
|
||||||
|
|
||||||
### 敏感信息提取
|
## 截图
|
||||||
|
### 主页
|
||||||
|

|
||||||
|
### 云函数捕获
|
||||||
|

|
||||||
|
### wx.api捕获
|
||||||
|

|
||||||
|
### 反编译文件编辑搜索
|
||||||
|

|
||||||
|
### Frist-MCP
|
||||||
|

|
||||||
|

|
||||||
|
### 自动更新
|
||||||
|

|
||||||
|
|
||||||

|
## 下载
|
||||||
|
|
||||||
<img src="https://s1.galgame.fun/imgb/u55/20260416_69e0be0c38e39.png" alt="PixPin_2026-04-16_18-45-59" />
|
[Releases](https://github.com/Spade-sec/First/releases)
|
||||||
|
|
||||||

|
| 平台 | 文件 |
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 功能特性
|
|
||||||
|
|
||||||
- 通过 Frida 注入微信客户端,转发小程序调试协议
|
|
||||||
- CDP 代理桥接,支持 Chrome DevTools 直接连接调试
|
|
||||||
- 路由枚举与一键跳转导航
|
|
||||||
- 云函数调用监控与参数分析
|
|
||||||
- UserScript 自动注入(支持按 URL 匹配、run-at 时机控制)
|
|
||||||
- 内置安全扫描模块,生成扫描报告
|
|
||||||
- 深色 / 浅色主题切换
|
|
||||||
- GUI(PySide6)与 CLI 双模式运行
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 环境要求
|
|
||||||
|
|
||||||
| 依赖 | 版本 |
|
|
||||||
|------|------|
|
|------|------|
|
||||||
| Python | >= 3.10 |
|
| macOS (Apple Silicon) | `First-ARM.dmg` |
|
||||||
| frida | >= 17.0.0 |
|
| macOS (Intel) | `First-Intel.dmg` |
|
||||||
| websockets | >= 12.0 |
|
| Windows | `First-Windows.zip` |
|
||||||
| protobuf | >= 4.0.0 |
|
|
||||||
| PySide6 | >= 6.5.0 |
|
|
||||||
|
|
||||||
安装依赖:
|
## 支持的微信版本
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
- WMPF 版本:11581, 11633, 13331, 13341, 13487, 13639, 13655, 13871, 13909, 14161, 14199, 14315, 16133, 16203, 16389, 16467, 16771, 16815, 16965, 17037, 17071, 17127, 18055, 18151, 18787, 18891, 18955, 19027, 19201(实时更新)
|
||||||
|
- 推荐微信版本:**4.1.0.30**
|
||||||
|
- 下载地址:[weixin/4.1.0.30](https://github.com/vs-olitus/wx-version/releases/tag/4.1.0.30)
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
- WMPF 版本:18152, 18788(实时更新)
|
||||||
|
- 推荐微信版本:**4.1.7.30**
|
||||||
|
- 下载地址:[weixin/4.1.7.30](https://github.com/vs-olitus/wx-version/releases/tag/4.1.7.30)
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
1. 打开 First
|
||||||
|
2. 点击启动 — Frida 自动注入微信
|
||||||
|
3. 在微信中打开小程序
|
||||||
|
4. 使用 DevTools / 云捕获 / 导航等功能
|
||||||
|
|
||||||
|
## macOS 注意事项
|
||||||
|
|
||||||
|
如果 Frida 注入报错,需要解除系统对进程附加的限制,任选其一:
|
||||||
|
|
||||||
|
**方案一:关闭 SIP(系统完整性保护)**
|
||||||
|
|
||||||
|
> 关闭后 Frida 才能正常注入进程。参考教程:[macOS SIP 开启关闭教程](https://cloud.tencent.com/developer/article/1496058)
|
||||||
|
|
||||||
|
**方案二:强制重签名 WeChat**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install -r requirements.txt
|
sudo codesign --force --deep --sign - /Applications/WeChat.app
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## 参考
|
||||||
|
|
||||||
## 微信版本要求
|
|
||||||
|
|
||||||
- WMPF版本支持列表:11581, 11633, 13331, 13341, 13487, 13639, 13655, 13871, 13909, 14161, 14199, 14315, 16133, 16203, 16389, 16467, 16771,
|
|
||||||
16815, 16965, 17037, 17071, 17127, 18055, 18151, 18787, 18891, 18955, 19027, 19201
|
|
||||||
- 推荐微信版本为4.1.0.30
|
|
||||||
- 下载地址[weixin/4.1.0.30](https://github.com/vs-olitus/wx-version/releases/tag/4.1.0.30)
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### GUI 模式(推荐)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python gui.py
|
|
||||||
```
|
|
||||||
双击启动.bat
|
|
||||||
启动后在主界面点击 **启动调试** 即可开始调试。
|
|
||||||
|
|
||||||
### 小程序页面操作
|
|
||||||
|
|
||||||
点击启动调试前请勿打开小程序, **启动调试**打开后再次启动**小程序**即可。
|
|
||||||
|
|
||||||
### CLI 模式
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 默认端口启动
|
|
||||||
python main.py
|
|
||||||
|
|
||||||
# 自定义端口
|
|
||||||
python main.py --cdp-port 62000
|
|
||||||
|
|
||||||
# 开启详细日志
|
|
||||||
python main.py --debug-main --debug-frida
|
|
||||||
```
|
|
||||||
### 连接 Chrome DevTools
|
|
||||||
|
|
||||||
启动后,在 Chrome 地址栏输入:
|
|
||||||
|
|
||||||
```
|
|
||||||
devtools://devtools/bundled/inspector.html?ws=127.0.0.1:62000
|
|
||||||
```
|
|
||||||
|
|
||||||
### 参数说明
|
|
||||||
|
|
||||||
| 参数 | 默认值 | 说明 |
|
|
||||||
|------|--------|------|
|
|
||||||
| `--debug-port` | `9421` | 远程调试服务端口 |
|
|
||||||
| `--cdp-port` | `62000` | CDP 代理监听端口 |
|
|
||||||
| `--debug-main` | 关闭 | 输出主进程调试日志 |
|
|
||||||
| `--debug-frida` | 关闭 | 输出 Frida 客户端日志 |
|
|
||||||
| `--scripts-dir` | `./userscripts` | UserScript 目录路径 |
|
|
||||||
| `--script` | — | 指定单个 .js 文件注入(可多次使用) |
|
|
||||||
|
|
||||||
### UserScript 注入
|
|
||||||
|
|
||||||
将 `.js` 脚本放入 `userscripts/` 目录,工具启动时自动加载并按规则注入。
|
|
||||||
|
|
||||||
也可手动指定文件:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python main.py --script ./my_hook.js --script ./another.js
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 打包为可执行文件
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pyinstaller WMPFDebugger.spec
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 常见问题解决办法
|
|
||||||
|
|
||||||
1. Frida 已显示连接,但小程序端显示未连接或无法断点调试
|
|
||||||
|
|
||||||
若操作顺序无误,建议先彻底卸载微信并重启电脑(如有重要聊天记录请提前备份)。
|
|
||||||
删除路径C:\Users\用户名\AppData\Roaming\Tencent\xwechat\XPlugin\Plugins\RadiumWMPF下所有以数字命名的文件夹,再次重启电脑后,安装微信 4.1.0.30 版本。安装完成后检查上述路径,确认文件夹编号为 16389。
|
|
||||||
|
|
||||||
## 参考项目
|
|
||||||
|
|
||||||
本项目参考并学习了以下优秀工具的实现思路:
|
|
||||||
|
|
||||||
- [evi0s/WMPFDebugger](https://github.com/evi0s/WMPFDebugger)
|
- [evi0s/WMPFDebugger](https://github.com/evi0s/WMPFDebugger)
|
||||||
- [0xsdeo/HeartK](https://github.com/0xsdeo/HeartK)
|
- [0xsdeo/HeartK](https://github.com/0xsdeo/HeartK)
|
||||||
- [残笑/FindSomething](https://github.com/momosecurity/FindSomething)
|
- [残笑/FindSomething](https://github.com/momosecurity/FindSomething)
|
||||||
- [进击的HACK/JSRPC与调用wx.cloud](https://mp.weixin.qq.com/s/hTlekrCPiMJCvsHYx7CAxw)
|
- [进击的HACK / JSRPC 与调用 wx.cloud](https://mp.weixin.qq.com/s/hTlekrCPiMJCvsHYx7CAxw)
|
||||||
---
|
- [linguo2625469/WMPFDebugger-mac](https://github.com/linguo2625469/WMPFDebugger-mac)
|
||||||
|
|
||||||
## 致谢
|
## 致谢
|
||||||
|
|
||||||
感谢 **0xsdeo** 师傅的大力支持与思路提供。
|
感谢 **0xsdeo** 师傅的大力支持与思路提供。
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 交流群
|
## 交流群
|
||||||
群满200变成手动挡了。加我拉
|
|
||||||

|
|
||||||
|
|
||||||
## 免责声明
|
群满 200 人后需要手动邀请,请加我拉群:
|
||||||
|
|
||||||
本工具仅供安全研究与学习使用,请勿用于未授权的目标,使用者须自行承担相关法律责任。
|
<img src="https://s1.galgame.fun/imgb/u55/20260601_6a1d196618084.png" alt="微信二维码" width="300" />
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"Version": 18788,
|
||||||
|
"Arch": {
|
||||||
|
"arm64": {
|
||||||
|
"LoadStartHookOffset": "0x4F0620C",
|
||||||
|
"LoadStartHookOffset2": "0x81CEC08",
|
||||||
|
"CDPFilterHookOffset": "0x81BFC04",
|
||||||
|
"ResourceCachePolicyHookOffset": "0x4F699E8",
|
||||||
|
"StructOffset": 1376
|
||||||
|
},
|
||||||
|
"x64": {
|
||||||
|
"LoadStartHookOffset": "0x5994BA0",
|
||||||
|
"LoadStartHookOffset2": "0x91FFB90",
|
||||||
|
"CDPFilterHookOffset": "0x91F1C20",
|
||||||
|
"ResourceCachePolicyHookOffset": "0x5A066E0",
|
||||||
|
"StructOffset": 1368
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"Version": 18152,
|
||||||
|
"Arch": {
|
||||||
|
"arm64": {
|
||||||
|
"LoadStartHookOffset": "0x4F43880",
|
||||||
|
"LoadStartHookOffset2": "0x8394F24",
|
||||||
|
"CDPFilterHookOffset": "0x8385F44",
|
||||||
|
"ResourceCachePolicyHookOffset": "0x4FA746C",
|
||||||
|
"StructOffset": 1376
|
||||||
|
},
|
||||||
|
"x64": {
|
||||||
|
"LoadStartHookOffset": "0x5971FF0",
|
||||||
|
"LoadStartHookOffset2": "0x91D58F0",
|
||||||
|
"CDPFilterHookOffset": "0x91C68D0",
|
||||||
|
"ResourceCachePolicyHookOffset": "0x59E0950",
|
||||||
|
"StructOffset": 1376
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"Version": 18788,
|
||||||
|
"Arch": {
|
||||||
|
"arm64": {
|
||||||
|
"LoadStartHookOffset": "0x4F6454C",
|
||||||
|
"LoadStartHookOffset2": "0x83BC8C8",
|
||||||
|
"CDPFilterHookOffset": "0x83AE884",
|
||||||
|
"ResourceCachePolicyHookOffset": "0x4FCAD90",
|
||||||
|
"StructOffset": 1368
|
||||||
|
},
|
||||||
|
"x64": {
|
||||||
|
"LoadStartHookOffset": "0x5994BA0",
|
||||||
|
"LoadStartHookOffset2": "0x91FFB90",
|
||||||
|
"CDPFilterHookOffset": "0x91F1C20",
|
||||||
|
"ResourceCachePolicyHookOffset": "0x5A066E0",
|
||||||
|
"StructOffset": 1368
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 11581,
|
"Version": 11581,
|
||||||
"LoadStartHookOffset": "0x28E9190",
|
"LoadStartHookOffset": "0x28E9190",
|
||||||
"CDPFilterHookOffset": "0x38C4350",
|
"CDPFilterHookOffset": "0x38C4350",
|
||||||
"SceneOffsets": [1208, 1160, 488]
|
"SceneOffsets": [56, 1208, 8, 1160, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 11633,
|
"Version": 11633,
|
||||||
"LoadStartHookOffset": "0x28F22A0",
|
"LoadStartHookOffset": "0x28F22A0",
|
||||||
"CDPFilterHookOffset": "0x38D41E0",
|
"CDPFilterHookOffset": "0x38D41E0",
|
||||||
"SceneOffsets": [1208, 1160, 488]
|
"SceneOffsets": [56, 1208, 8, 1160, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13331,
|
"Version": 13331,
|
||||||
"LoadStartHookOffset": "0x0FFC200",
|
"LoadStartHookOffset": "0x0FFC200",
|
||||||
"CDPFilterHookOffset": "0x2420100",
|
"CDPFilterHookOffset": "0x2420100",
|
||||||
"SceneOffsets": [1272, 1224, 488]
|
"SceneOffsets": [56, 1272, 8, 1224, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13341,
|
"Version": 13341,
|
||||||
"LoadStartHookOffset": "0x10009E0",
|
"LoadStartHookOffset": "0x10009E0",
|
||||||
"CDPFilterHookOffset": "0x242E8E0",
|
"CDPFilterHookOffset": "0x242E8E0",
|
||||||
"SceneOffsets": [1272, 1224, 488]
|
"SceneOffsets": [56, 1272, 8, 1224, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13487,
|
"Version": 13487,
|
||||||
"LoadStartHookOffset": "0x0FFB600",
|
"LoadStartHookOffset": "0x0FFB600",
|
||||||
"CDPFilterHookOffset": "0x241FEB0",
|
"CDPFilterHookOffset": "0x241FEB0",
|
||||||
"SceneOffsets": [1272, 1224, 488]
|
"SceneOffsets": [56, 1272, 8, 1224, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13639,
|
"Version": 13639,
|
||||||
"LoadStartHookOffset": "0x1000990",
|
"LoadStartHookOffset": "0x1000990",
|
||||||
"CDPFilterHookOffset": "0x2424DE0",
|
"CDPFilterHookOffset": "0x2424DE0",
|
||||||
"SceneOffsets": [1272, 1224, 488]
|
"SceneOffsets": [56, 1272, 8, 1224, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13655,
|
"Version": 13655,
|
||||||
"LoadStartHookOffset": "0x100F4B0",
|
"LoadStartHookOffset": "0x100F4B0",
|
||||||
"CDPFilterHookOffset": "0x244A9E0",
|
"CDPFilterHookOffset": "0x244A9E0",
|
||||||
"SceneOffsets": [1280, 1232, 488]
|
"SceneOffsets": [56, 1280, 8, 1232, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13871,
|
"Version": 13871,
|
||||||
"LoadStartHookOffset": "0x101F160",
|
"LoadStartHookOffset": "0x101F160",
|
||||||
"CDPFilterHookOffset": "0x246FC40",
|
"CDPFilterHookOffset": "0x246FC40",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 13909,
|
"Version": 13909,
|
||||||
"LoadStartHookOffset": "0x101F0E0",
|
"LoadStartHookOffset": "0x101F0E0",
|
||||||
"CDPFilterHookOffset": "0x246FDC0",
|
"CDPFilterHookOffset": "0x246FDC0",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 14161,
|
"Version": 14161,
|
||||||
"LoadStartHookOffset": "0x10246C0",
|
"LoadStartHookOffset": "0x10246C0",
|
||||||
"CDPFilterHookOffset": "0x24839B0",
|
"CDPFilterHookOffset": "0x24839B0",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 14199,
|
"Version": 14199,
|
||||||
"LoadStartHookOffset": "0x10246F0",
|
"LoadStartHookOffset": "0x10246F0",
|
||||||
"CDPFilterHookOffset": "0x24839E0",
|
"CDPFilterHookOffset": "0x24839E0",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 14315,
|
"Version": 14315,
|
||||||
"LoadStartHookOffset": "0x10004C0",
|
"LoadStartHookOffset": "0x10004C0",
|
||||||
"CDPFilterHookOffset": "0x2424B50",
|
"CDPFilterHookOffset": "0x2424B50",
|
||||||
"SceneOffsets": [1272, 1224, 488]
|
"SceneOffsets": [56, 1272, 8, 1224, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16133,
|
"Version": 16133,
|
||||||
"LoadStartHookOffset": "0x470FAD0",
|
"LoadStartHookOffset": "0x470FAD0",
|
||||||
"CDPFilterHookOffset": "0x90FC7E0",
|
"CDPFilterHookOffset": "0x90FC7E0",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16203,
|
"Version": 16203,
|
||||||
"LoadStartHookOffset": "0x4710890",
|
"LoadStartHookOffset": "0x4710890",
|
||||||
"CDPFilterHookOffset": "0x90FD640",
|
"CDPFilterHookOffset": "0x90FD640",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16389,
|
"Version": 16389,
|
||||||
"LoadStartHookOffset": "0x24E4830",
|
"LoadStartHookOffset": "0x24E4830",
|
||||||
"CDPFilterHookOffset": "0x2E2A880",
|
"CDPFilterHookOffset": "0x2E2A880",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16467,
|
"Version": 16467,
|
||||||
"LoadStartHookOffset": "0x24E4FD0",
|
"LoadStartHookOffset": "0x24E4FD0",
|
||||||
"CDPFilterHookOffset": "0x2E2CC90",
|
"CDPFilterHookOffset": "0x2E2CC90",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16771,
|
"Version": 16771,
|
||||||
"LoadStartHookOffset": "0x24E9130",
|
"LoadStartHookOffset": "0x24E9130",
|
||||||
"CDPFilterHookOffset": "0x2E3C470",
|
"CDPFilterHookOffset": "0x2E3C470",
|
||||||
"SceneOffsets": [1360, 1312, 488]
|
"SceneOffsets": [56, 1360, 8, 1312, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16815,
|
"Version": 16815,
|
||||||
"LoadStartHookOffset": "0x2509690",
|
"LoadStartHookOffset": "0x2509690",
|
||||||
"CDPFilterHookOffset": "0x2E768D0",
|
"CDPFilterHookOffset": "0x2E768D0",
|
||||||
"SceneOffsets": [1416, 1360, 488]
|
"SceneOffsets": [56, 1416, 8, 1360, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 16965,
|
"Version": 16965,
|
||||||
"LoadStartHookOffset": "0x2570220",
|
"LoadStartHookOffset": "0x2570220",
|
||||||
"CDPFilterHookOffset": "0x2F844A0",
|
"CDPFilterHookOffset": "0x2F844A0",
|
||||||
"SceneOffsets": [1416, 1360, 488]
|
"SceneOffsets": [56, 1416, 8, 1360, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 17037,
|
"Version": 17037,
|
||||||
"LoadStartHookOffset": "0x257D0A0",
|
"LoadStartHookOffset": "0x257D0A0",
|
||||||
"CDPFilterHookOffset": "0x2FB2310",
|
"CDPFilterHookOffset": "0x2FB2310",
|
||||||
"SceneOffsets": [1408, 1352, 488]
|
"SceneOffsets": [56, 1408, 8, 1352, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 17071,
|
"Version": 17071,
|
||||||
"LoadStartHookOffset": "0x258F370",
|
"LoadStartHookOffset": "0x258F370",
|
||||||
"CDPFilterHookOffset": "0x2FD3080",
|
"CDPFilterHookOffset": "0x2FD3080",
|
||||||
"SceneOffsets": [1408, 1352, 488]
|
"SceneOffsets": [56, 1408, 8, 1352, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 17127,
|
"Version": 17127,
|
||||||
"LoadStartHookOffset": "0x2590910",
|
"LoadStartHookOffset": "0x2590910",
|
||||||
"CDPFilterHookOffset": "0x2FD4040",
|
"CDPFilterHookOffset": "0x2FD4040",
|
||||||
"SceneOffsets": [1408, 1352, 488]
|
"SceneOffsets": [56, 1408, 8, 1352, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 18055,
|
"Version": 18055,
|
||||||
"LoadStartHookOffset": "0x25A1040",
|
"LoadStartHookOffset": "0x25A1040",
|
||||||
"CDPFilterHookOffset": "0x30031E0",
|
"CDPFilterHookOffset": "0x30031E0",
|
||||||
"SceneOffsets": [1416, 1352, 488]
|
"SceneOffsets": [56, 1416, 8, 1352, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 18151,
|
"Version": 18151,
|
||||||
"LoadStartHookOffset": "0x25A2E20",
|
"LoadStartHookOffset": "0x25A2E20",
|
||||||
"CDPFilterHookOffset": "0x3013D20",
|
"CDPFilterHookOffset": "0x3013D20",
|
||||||
"SceneOffsets": [1416, 1352, 488]
|
"SceneOffsets": [56, 1416, 8, 1352, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 18787,
|
"Version": 18787,
|
||||||
"LoadStartHookOffset": "0x25B2870",
|
"LoadStartHookOffset": "0x25B2870",
|
||||||
"CDPFilterHookOffset": "0x3028AD0",
|
"CDPFilterHookOffset": "0x3028AD0",
|
||||||
"SceneOffsets": [1408, 1344, 488]
|
"SceneOffsets": [56, 1408, 8, 1344, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 18891,
|
"Version": 18891,
|
||||||
"LoadStartHookOffset": "0x25B50C0",
|
"LoadStartHookOffset": "0x25B50C0",
|
||||||
"CDPFilterHookOffset": "0x30245E0",
|
"CDPFilterHookOffset": "0x30245E0",
|
||||||
"SceneOffsets": [1408, 1344, 488]
|
"SceneOffsets": [56, 1408, 8, 1344, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 18955,
|
"Version": 18955,
|
||||||
"LoadStartHookOffset": "0x25B52C0",
|
"LoadStartHookOffset": "0x25B52C0",
|
||||||
"CDPFilterHookOffset": "0x30248B0",
|
"CDPFilterHookOffset": "0x30248B0",
|
||||||
"SceneOffsets": [1408, 1344, 488]
|
"SceneOffsets": [56, 1408, 8, 1344, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 19027,
|
"Version": 19027,
|
||||||
"LoadStartHookOffset": "0x25B52D0",
|
"LoadStartHookOffset": "0x25B52D0",
|
||||||
"CDPFilterHookOffset": "0x3024AD0",
|
"CDPFilterHookOffset": "0x3024AD0",
|
||||||
"SceneOffsets": [1408, 1344, 488]
|
"SceneOffsets": [56, 1408, 8, 1344, 16, 488]
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"Version": 19201,
|
"Version": 19201,
|
||||||
"LoadStartHookOffset": "0x25B5DD0",
|
"LoadStartHookOffset": "0x25B5DD0",
|
||||||
"CDPFilterHookOffset": "0x301B3C0",
|
"CDPFilterHookOffset": "0x301B3C0",
|
||||||
"SceneOffsets": [1376, 1312, 456]
|
"SceneOffsets": [56, 1376, 8, 1312, 16, 456]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"Version": 19339,
|
||||||
|
"LoadStartHookOffset": "0x25B5DD0",
|
||||||
|
"CDPFilterHookOffset": "0x301BA00",
|
||||||
|
"SceneOffsets": [56, 1376, 8, 1312, 16, 456]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"Version": 19459,
|
||||||
|
"LoadStartHookOffset": "0x25BB580",
|
||||||
|
"CDPFilterHookOffset": "0x3022F20",
|
||||||
|
"SceneOffsets": [56, 1376, 8, 1312, 16, 456]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"Version": 19481,
|
||||||
|
"LoadStartHookOffset": "0x25BBA80",
|
||||||
|
"CDPFilterHookOffset": "0x3023420",
|
||||||
|
"SceneOffsets": [56, 1376, 8, 1312, 16, 456]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"Version": 19749,
|
||||||
|
"LoadStartHookOffset": "0x25E77C0",
|
||||||
|
"CDPFilterHookOffset": "0x30ABC60",
|
||||||
|
"SceneOffsets": [64, 1408, 8, 1344, 16, 456]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"Version": 19769,
|
||||||
|
"LoadStartHookOffset": "0x25E7990",
|
||||||
|
"CDPFilterHookOffset": "0x30AC0A0",
|
||||||
|
"SceneOffsets": [64, 1408, 8, 1344, 16, 456]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"Version": 19823,
|
||||||
|
"LoadStartHookOffset": "0x25ED1C0",
|
||||||
|
"CDPFilterHookOffset": "0x30B3320",
|
||||||
|
"SceneOffsets": [64, 1408, 8, 1344, 16, 456]
|
||||||
|
}
|
||||||
+198
-74
@@ -1,119 +1,243 @@
|
|||||||
|
const VERBOSE = false;
|
||||||
|
const PLATFORM = Process.platform; // 'darwin' | 'windows'
|
||||||
|
const ARCH = Process.arch; // 'arm64' | 'x64' | 'x86_64' | ...
|
||||||
|
|
||||||
|
// ── Module Resolution ──
|
||||||
|
|
||||||
const getMainModule = (version) => {
|
const getMainModule = (version) => {
|
||||||
|
if (PLATFORM === "darwin") {
|
||||||
|
return Process.findModuleByName("WeChatAppEx Framework");
|
||||||
|
}
|
||||||
|
// Windows: flue.dll for newer versions
|
||||||
if (version >= 13331) {
|
if (version >= 13331) {
|
||||||
return Process.findModuleByName("flue.dll");
|
return Process.findModuleByName("flue.dll");
|
||||||
}
|
}
|
||||||
return Process.findModuleByName("WeChatAppEx.exe");
|
return Process.findModuleByName("WeChatAppEx.exe");
|
||||||
};
|
};
|
||||||
|
|
||||||
const patchCDPFilter = (base, config) => {
|
// ── Scene Values ──
|
||||||
// xref: SendToClientFilter OR devtools_message_filter_applet_webview.cc
|
|
||||||
const offset = config.CDPFilterHookOffset;
|
const SCENE_WHITELIST = [
|
||||||
|
1005, 1007, 1008, 1012, 1027, 1035, 1053, 1074,
|
||||||
|
1145, 1168, 1178, 1256, 1260, 1302, 1308,
|
||||||
|
];
|
||||||
|
|
||||||
|
// ── CDP Filter Patch (shared logic, platform-specific pointer access) ──
|
||||||
|
|
||||||
|
const patchCDPFilter = (base, offset) => {
|
||||||
|
// xref: SendToClientFilter / devtools_message_filter_applet_webview.cc
|
||||||
Interceptor.attach(base.add(offset), {
|
Interceptor.attach(base.add(offset), {
|
||||||
onEnter(args) {
|
onEnter(args) {
|
||||||
send(
|
if (PLATFORM === "windows") {
|
||||||
`[patch] CDP filter on enter, original value of input: ${args[0].readPointer()}`,
|
this.inputValue = args[0];
|
||||||
);
|
}
|
||||||
this.inputValue = args[0];
|
|
||||||
},
|
},
|
||||||
onLeave(retval) {
|
onLeave(retval) {
|
||||||
const inputValue = this.inputValue.readPointer();
|
let target;
|
||||||
if (inputValue.isNull() || inputValue.add(8).isNull()) {
|
if (PLATFORM === "darwin") {
|
||||||
// there's a chance the value could be null
|
// macOS: retval points directly to the struct
|
||||||
// return here to avoid crash
|
if (!retval || retval.isNull()) return;
|
||||||
return;
|
target = retval.add(8);
|
||||||
|
} else {
|
||||||
|
// Windows: dereference args[0] to get the struct pointer
|
||||||
|
const ptr = this.inputValue.readPointer();
|
||||||
|
if (ptr.isNull() || ptr.add(8).isNull()) return;
|
||||||
|
target = ptr.add(8);
|
||||||
}
|
}
|
||||||
|
VERBOSE && console.log(`[patch] CDP filter v8[2]: ${target.readU32()}`);
|
||||||
send(
|
if (target.readU32() === 6) {
|
||||||
`[patch] CDP filter on leave, patch input, now value: ${inputValue}; ` +
|
target.writeU32(0x0);
|
||||||
`*(input + 8) = ${inputValue.add(8).readU32()}`,
|
|
||||||
);
|
|
||||||
if (inputValue.add(8).readU32() == 6) {
|
|
||||||
inputValue.add(8).writeU32(0x0);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const hookOnLoadScene = (a1, sceneOffsets) => {
|
// ── Resource Cache Policy Patch (darwin only) ──
|
||||||
const miniappConfigPtr = a1
|
|
||||||
.add(56)
|
|
||||||
.readPointer()
|
|
||||||
.add(sceneOffsets[0])
|
|
||||||
.readPointer();
|
|
||||||
const miniappScenePtr = miniappConfigPtr
|
|
||||||
.add(8)
|
|
||||||
.readPointer()
|
|
||||||
.add(sceneOffsets[1])
|
|
||||||
.readPointer()
|
|
||||||
.add(16)
|
|
||||||
.readPointer()
|
|
||||||
.add(488);
|
|
||||||
send(`[hook] scene: ${miniappScenePtr.readInt()}`);
|
|
||||||
|
|
||||||
// 1000: from issue #83 <-- will crash the process
|
const patchResourceCachePolicy = (base, offset) => {
|
||||||
// 1007: from issue #80
|
// xref: WAPCAdapterAppIndex.js
|
||||||
// 1008: from issue #53
|
Interceptor.attach(base.add(offset), {
|
||||||
// 1027: from issue #78
|
onLeave(retval) {
|
||||||
// 1035: from issue #78
|
VERBOSE && console.log(`[patch] cache policy retval: ${retval.toInt32()} -> 0`);
|
||||||
// 1053: from issue #25
|
retval.replace(0x0);
|
||||||
// 1074: from issue #32
|
},
|
||||||
// 1145: from search
|
});
|
||||||
// 1178: from phone (issue #117)
|
|
||||||
// 1256: from recent
|
|
||||||
// 1260: from frequently used
|
|
||||||
// 1302: from services
|
|
||||||
// 1308: minigame?
|
|
||||||
const sceneNumberArray = [
|
|
||||||
1005, 1007, 1008, 1027, 1035, 1053, 1074, 1145, 1178, 1256, 1260, 1302,
|
|
||||||
1308,
|
|
||||||
];
|
|
||||||
if (!sceneNumberArray.includes(miniappScenePtr.readInt())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
send("[hook] hook scene condition -> 1101");
|
|
||||||
miniappScenePtr.writeInt(1101);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const patchOnLoadStart = (base, config) => {
|
// ── OnLoadStart: Darwin ──
|
||||||
// xref: AppletIndexContainer::OnLoadStart
|
|
||||||
Interceptor.attach(base.add(config.LoadStartHookOffset), {
|
const darwinPatchLoadStart = (base, offset) => {
|
||||||
|
// xref: AppletIndexContainer::OnLoadStart (first match)
|
||||||
|
// Force debug mode by setting second param to true
|
||||||
|
Interceptor.attach(base.add(offset), {
|
||||||
|
onEnter() {
|
||||||
|
console.log("[hook] AppletIndexContainer::OnLoadStart onEnter");
|
||||||
|
if (ARCH === "arm64") {
|
||||||
|
this.context.x1 = (this.context.x1 & ~0xff) | 0x1;
|
||||||
|
} else {
|
||||||
|
// x64 / x86_64: System V ABI, second param = RSI
|
||||||
|
this.context.rsi = (this.context.rsi & ~0xff) | 0x1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLeave() {},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const darwinPatchLoadStart2 = (base, offset, structOffset) => {
|
||||||
|
// xref: AppletIndexContainer::OnLoadStart (last function)
|
||||||
|
// Hijack scene value via struct pointer chain
|
||||||
|
Interceptor.attach(base.add(offset), {
|
||||||
onEnter(args) {
|
onEnter(args) {
|
||||||
send(
|
try {
|
||||||
`[inteceptor] AppletIndexContainer::OnLoadStart onEnter, ` +
|
const v4 = args[0].add(8).readPointer();
|
||||||
`indexContainer.this: ${this.context.rcx}`,
|
if (!v4 || v4.isNull()) return;
|
||||||
);
|
const q1 = v4.add(structOffset).readPointer();
|
||||||
// write dl to 0x1
|
if (!q1 || q1.isNull()) return;
|
||||||
|
const q2 = q1.add(16).readPointer();
|
||||||
|
if (!q2 || q2.isNull()) return;
|
||||||
|
const scenePtr = q2.add(488);
|
||||||
|
const scene = scenePtr.readInt();
|
||||||
|
console.log(`[hook] scene: ${scene}`);
|
||||||
|
if (SCENE_WHITELIST.includes(scene)) {
|
||||||
|
console.log("[hook] hook scene -> 1101");
|
||||||
|
scenePtr.writeInt(1101);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[hook] onLoadStart2 error: ${e}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLeave() {},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// ── OnLoadStart: Windows ──
|
||||||
|
|
||||||
|
const winPatchLoadStart = (base, config) => {
|
||||||
|
// xref: AppletIndexContainer::OnLoadStart
|
||||||
|
// Windows combines debug flag + scene hijack in one hook
|
||||||
|
Interceptor.attach(base.add(config.LoadStartHookOffset), {
|
||||||
|
onEnter() {
|
||||||
|
// Microsoft x64 ABI: second param = RDX, force debug mode
|
||||||
if ((this.context.rdx & 0xff) !== 1) {
|
if ((this.context.rdx & 0xff) !== 1) {
|
||||||
this.context.rdx = (this.context.rdx & ~0xff) | 0x1;
|
this.context.rdx = (this.context.rdx & ~0xff) | 0x1;
|
||||||
}
|
}
|
||||||
// handle onLoad scene
|
// Scene hijack via SceneOffsets pointer chain
|
||||||
hookOnLoadScene(this.context.rcx, config.SceneOffsets);
|
try {
|
||||||
},
|
const offsets = config.SceneOffsets;
|
||||||
onLeave(retval) {
|
const miniappConfigPtr = this.context.rcx
|
||||||
// do nothing
|
.add(offsets[0])
|
||||||
|
.readPointer()
|
||||||
|
.add(offsets[1])
|
||||||
|
.readPointer();
|
||||||
|
const scenePtr = miniappConfigPtr
|
||||||
|
.add(offsets[2])
|
||||||
|
.readPointer()
|
||||||
|
.add(offsets[3])
|
||||||
|
.readPointer()
|
||||||
|
.add(offsets[4])
|
||||||
|
.readPointer()
|
||||||
|
.add(offsets[5]);
|
||||||
|
const scene = scenePtr.readInt();
|
||||||
|
send(`[hook] scene: ${scene}`);
|
||||||
|
if (SCENE_WHITELIST.includes(scene)) {
|
||||||
|
send("[hook] hook scene -> 1101");
|
||||||
|
scenePtr.writeInt(1101);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
send(`[hook] scene hook error: ${e}`);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
onLeave() {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Config Parsing ──
|
||||||
|
|
||||||
const parseConfig = () => {
|
const parseConfig = () => {
|
||||||
const rawConfig = `@@CONFIG@@`;
|
const rawConfig = `@@CONFIG@@`;
|
||||||
if (rawConfig.includes("@@")) {
|
if (rawConfig.includes("@@")) {
|
||||||
// test addresses
|
// Fallback test config
|
||||||
|
if (PLATFORM === "darwin") {
|
||||||
|
return {
|
||||||
|
Version: 17078,
|
||||||
|
Arch: {
|
||||||
|
arm64: {
|
||||||
|
LoadStartHookOffset: "0x4F0620C",
|
||||||
|
LoadStartHookOffset2: "0x81CEC08",
|
||||||
|
CDPFilterHookOffset: "0x81BFC04",
|
||||||
|
ResourceCachePolicyHookOffset: "0x4F699E8",
|
||||||
|
StructOffset: 1376,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
Version: 18955,
|
Version: 18955,
|
||||||
LoadStartHookOffset: "0x25B52C0",
|
LoadStartHookOffset: "0x25B52C0",
|
||||||
CDPFilterHookOffset: "0x30248B0",
|
CDPFilterHookOffset: "0x30248B0",
|
||||||
SceneOffsets: [1408, 1344],
|
SceneOffsets: [56, 1408, 8, 1344, 16, 488],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return JSON.parse(rawConfig);
|
return JSON.parse(rawConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolveArchConfig = (config) => {
|
||||||
|
// Windows configs have offsets at top level — return directly
|
||||||
|
if (config && config.LoadStartHookOffset) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
// Mac configs nest under Arch.{arm64|x64}
|
||||||
|
const table = config?.Arch || config?.arch;
|
||||||
|
if (!table) return null;
|
||||||
|
|
||||||
|
const candidates = [ARCH];
|
||||||
|
if (ARCH === "x86_64") candidates.push("x64");
|
||||||
|
if (ARCH === "amd64") candidates.push("x64");
|
||||||
|
|
||||||
|
for (const key of candidates) {
|
||||||
|
const picked = table[key];
|
||||||
|
if (picked && picked.LoadStartHookOffset) {
|
||||||
|
return { ...picked, Version: config.Version, __arch: key };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ── Main ──
|
||||||
|
|
||||||
const main = () => {
|
const main = () => {
|
||||||
const config = parseConfig();
|
const rawConfig = parseConfig();
|
||||||
|
const config = resolveArchConfig(rawConfig);
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
console.error(`[frida] no config for platform=${PLATFORM} arch=${ARCH}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const mainModule = getMainModule(config.Version);
|
const mainModule = getMainModule(config.Version);
|
||||||
patchOnLoadStart(mainModule.base, config);
|
if (!mainModule) {
|
||||||
patchCDPFilter(mainModule.base, config);
|
const expected = PLATFORM === "darwin" ? "WeChatAppEx Framework" : "flue.dll / WeChatAppEx.exe";
|
||||||
|
console.error(`[frida] module not found: ${expected}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[frida] version=${config.Version} platform=${PLATFORM} arch=${config.__arch || ARCH}`);
|
||||||
|
console.log(`[frida] module base: ${mainModule.base}`);
|
||||||
|
|
||||||
|
const base = mainModule.base;
|
||||||
|
|
||||||
|
// CDP filter patch — both platforms
|
||||||
|
patchCDPFilter(base, config.CDPFilterHookOffset);
|
||||||
|
|
||||||
|
if (PLATFORM === "darwin") {
|
||||||
|
darwinPatchLoadStart(base, config.LoadStartHookOffset);
|
||||||
|
darwinPatchLoadStart2(base, config.LoadStartHookOffset2, config.StructOffset);
|
||||||
|
if (config.ResourceCachePolicyHookOffset) {
|
||||||
|
patchResourceCachePolicy(base, config.ResourceCachePolicyHookOffset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
winPatchLoadStart(base, config);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|||||||
+9
-2
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"theme": "dark",
|
"theme": "dark",
|
||||||
"debug_port": "9421",
|
|
||||||
"cdp_port": "62000",
|
"cdp_port": "62000",
|
||||||
"debug_main": false,
|
"debug_main": false,
|
||||||
"debug_frida": false,
|
"debug_frida": false,
|
||||||
"selected_preload_scripts": []
|
"extract_packages_dir": "",
|
||||||
|
"extract_custom_patterns": {},
|
||||||
|
"auto_decompile": false,
|
||||||
|
"auto_scan": false,
|
||||||
|
"global_hook_scripts": [],
|
||||||
|
"font_ui": "PingFang SC",
|
||||||
|
"font_ui_size": 12,
|
||||||
|
"font_mono": "Menlo",
|
||||||
|
"font_mono_size": 15
|
||||||
}
|
}
|
||||||
+230
@@ -0,0 +1,230 @@
|
|||||||
|
# First
|
||||||
|
|
||||||
|
> 微信小程序安全调试工具 —— 基于 Frida + CDP 代理,支持 Windows / macOS 双平台,GUI 与 CLI 双模式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 截图预览
|
||||||
|
|
||||||
|
### 主界面
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 路由导航
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 云函数分析
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 调试开关(JSRPC / wx.cloud 调用)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 敏感信息提取
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<img src="https://s1.galgame.fun/imgb/u55/20260416_69e0be0c38e39.png" alt="敏感信息提取-2" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- Frida 动态注入微信客户端,转发小程序调试协议
|
||||||
|
- CDP 代理桥接,Chrome DevTools 直连调试
|
||||||
|
- 路由枚举、分类与一键跳转
|
||||||
|
- 云函数调用监控与参数分析(动态 Hook + 静态扫描)
|
||||||
|
- UserScript 自动注入(支持 URL 匹配、run-at 时机控制)
|
||||||
|
- wxapkg 解密解包 + 敏感信息扫描(IP / 密钥 / 云存储 / JWT 等)
|
||||||
|
- 深色 / 浅色主题切换
|
||||||
|
- GUI(PySide6)与 CLI 双模式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
| 依赖 | 版本 |
|
||||||
|
|------|------|
|
||||||
|
| Python | >= 3.10 |
|
||||||
|
| frida | >= 17.0.0 |
|
||||||
|
| websockets | >= 12.0 |
|
||||||
|
| protobuf | >= 4.0.0 |
|
||||||
|
| PySide6 | >= 6.5.0 |
|
||||||
|
| pycryptodome | 最新版 |
|
||||||
|
|
||||||
|
安装依赖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 支持的微信版本
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
- WMPF 版本:11581, 11633, 13331, 13341, 13487, 13639, 13655, 13871, 13909, 14161, 14199, 14315, 16133, 16203, 16389, 16467, 16771, 16815, 16965, 17037, 17071, 17127, 18055, 18151, 18787, 18891, 18955, 19027, 19201
|
||||||
|
- 推荐微信版本:**4.1.0.30**
|
||||||
|
- 下载地址:[weixin/4.1.0.30](https://github.com/vs-olitus/wx-version/releases/tag/4.1.0.30)
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
- WMPF 版本:18152, 18788
|
||||||
|
- 推荐微信版本:**4.1.7.30**
|
||||||
|
- 下载地址:[weixin/4.1.7.30](https://github.com/vs-olitus/wx-version/releases/tag/4.1.7.30)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
**一键启动:** 双击 `启动.bat`,首次运行会自动安装依赖。
|
||||||
|
|
||||||
|
**手动启动:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python gui.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
**一键启动:** 终端执行 `./启动.sh`,首次运行会自动安装依赖。
|
||||||
|
|
||||||
|
**手动启动:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 gui.py
|
||||||
|
```
|
||||||
|
|
||||||
|
启动后在主界面点击 **启动调试**,然后再打开小程序即可(请勿在启动调试前打开小程序)。
|
||||||
|
|
||||||
|
### CLI 模式
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 默认端口启动
|
||||||
|
python main.py
|
||||||
|
|
||||||
|
# 自定义端口
|
||||||
|
python main.py --cdp-port 62000
|
||||||
|
|
||||||
|
# 开启详细日志
|
||||||
|
python main.py --debug-main --debug-frida
|
||||||
|
```
|
||||||
|
|
||||||
|
### 连接 Chrome DevTools
|
||||||
|
|
||||||
|
启动后,在 Chrome 地址栏输入:
|
||||||
|
|
||||||
|
```
|
||||||
|
devtools://devtools/bundled/inspector.html?ws=127.0.0.1:62000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 服务号调试操作
|
||||||
|
|
||||||
|
1. 打开一个小程序页面作为占位(保持不关闭)
|
||||||
|
2. 访问需要调试的服务号内容(如 H5 网页)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
3. 在工具栏「服务」目标列表中找到目标网页,双击后切换至调试视图即可开始调试
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## macOS 注意事项
|
||||||
|
|
||||||
|
如果 Frida 注入报错,需要解除系统对进程附加的限制,任选其一:
|
||||||
|
|
||||||
|
**方案一:关闭 SIP(系统完整性保护)**
|
||||||
|
|
||||||
|
> 关闭后 Frida 才能正常注入进程。参考教程:[macOS SIP 开启关闭教程](https://cloud.tencent.com/developer/article/1496058)
|
||||||
|
|
||||||
|
**方案二:强制重签名 WeChat**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo codesign --force --deep --sign - /Applications/WeChat.app
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 参数说明
|
||||||
|
|
||||||
|
| 参数 | 默认值 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `--debug-port` | `9421` | 远程调试服务端口 |
|
||||||
|
| `--cdp-port` | `62000` | CDP 代理监听端口 |
|
||||||
|
| `--debug-main` | 关闭 | 输出主进程调试日志 |
|
||||||
|
| `--debug-frida` | 关闭 | 输出 Frida 客户端日志 |
|
||||||
|
| `--scripts-dir` | `./userscripts` | UserScript 目录路径 |
|
||||||
|
| `--script` | — | 指定单个 .js 文件注入(可多次使用) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## UserScript 注入
|
||||||
|
|
||||||
|
将 `.js` 脚本放入 `userscripts/` 目录,启动时自动加载并注入。也可手动指定:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py --script ./my_hook.js --script ./another.js
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 打包为可执行文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pyinstaller WMPFDebugger.spec
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
**Q: Frida 已连接,但小程序端显示未连接或无法断点调试?**
|
||||||
|
|
||||||
|
确认操作顺序无误后,尝试以下步骤:
|
||||||
|
|
||||||
|
1. 彻底卸载微信并重启电脑(重要聊天记录请提前备份)
|
||||||
|
2. 删除 `C:\Users\用户名\AppData\Roaming\Tencent\xwechat\XPlugin\Plugins\RadiumWMPF` 下所有数字命名的文件夹
|
||||||
|
3. 再次重启后安装微信 4.1.0.30 版本
|
||||||
|
4. 检查上述路径,确认文件夹编号为 `16389`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 参考项目
|
||||||
|
|
||||||
|
- [evi0s/WMPFDebugger](https://github.com/evi0s/WMPFDebugger)
|
||||||
|
- [0xsdeo/HeartK](https://github.com/0xsdeo/HeartK)
|
||||||
|
- [残笑/FindSomething](https://github.com/momosecurity/FindSomething)
|
||||||
|
- [进击的HACK / JSRPC 与调用 wx.cloud](https://mp.weixin.qq.com/s/hTlekrCPiMJCvsHYx7CAxw)
|
||||||
|
- [linguo2625469/WMPFDebugger-mac](https://github.com/linguo2625469/WMPFDebugger-mac)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
感谢 **0xsdeo** 师傅的大力支持与思路提供。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 交流群
|
||||||
|
|
||||||
|
群满 200 人后需要手动邀请,请加我拉群:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 免责声明
|
||||||
|
|
||||||
|
本工具仅供安全研究与学习使用,请勿用于未授权的目标,使用者须自行承担相关法律责任。
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[project]
|
||||||
|
name = "first"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "WeChat mini program security debugging tool based on Frida and CDP proxy."
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
"frida>=17.0.0",
|
||||||
|
"websockets>=12.0",
|
||||||
|
"protobuf>=4.0.0",
|
||||||
|
"pyside6>=6.5.0",
|
||||||
|
"pycryptodome",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.uv]
|
||||||
|
package = false
|
||||||
@@ -2,3 +2,4 @@ frida>=17.0.0
|
|||||||
websockets>=12.0
|
websockets>=12.0
|
||||||
protobuf>=4.0.0
|
protobuf>=4.0.0
|
||||||
PySide6>=6.5.0
|
PySide6>=6.5.0
|
||||||
|
pycryptodome
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+86
-43
@@ -4,7 +4,9 @@ DebugEngine - wraps debug_server, proxy_server, frida_server into a reusable cla
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
|
import platform
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -434,66 +436,95 @@ class DebugEngine:
|
|||||||
|
|
||||||
# ── Frida ──
|
# ── Frida ──
|
||||||
|
|
||||||
async def _start_frida(self):
|
# ── Frida: platform helpers ──
|
||||||
logger = self.logger
|
|
||||||
|
def _get_project_root(self):
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
return Path(getattr(sys, '_MEIPASS', Path(sys.executable).parent)).resolve()
|
||||||
|
return Path(__file__).parent.parent.resolve()
|
||||||
|
|
||||||
|
def _find_wmpf_pids_win(self):
|
||||||
|
"""Windows: find main WeChatAppEx.exe PID via ppid frequency."""
|
||||||
device = frida.get_local_device()
|
device = frida.get_local_device()
|
||||||
processes = device.enumerate_processes(scope="metadata")
|
processes = device.enumerate_processes(scope="metadata")
|
||||||
wmpf_processes = [p for p in processes if p.name == "WeChatAppEx.exe"]
|
wmpf_procs = [p for p in processes if p.name == "WeChatAppEx.exe"]
|
||||||
if not wmpf_processes:
|
if not wmpf_procs:
|
||||||
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
|
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
|
||||||
|
|
||||||
wmpf_ppids = []
|
ppids = [p.parameters.get("ppid", 0) or 0 for p in wmpf_procs]
|
||||||
for p in wmpf_processes:
|
main_pid = Counter(ppids).most_common(1)[0][0]
|
||||||
ppid = p.parameters.get("ppid", 0)
|
if main_pid == 0:
|
||||||
wmpf_ppids.append(ppid if ppid else 0)
|
raise RuntimeError("[frida] WeChatAppEx.exe main process not found")
|
||||||
|
|
||||||
if not wmpf_ppids:
|
main_proc = next((p for p in processes if p.pid == main_pid), None)
|
||||||
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
|
if main_proc is None:
|
||||||
|
raise RuntimeError("[frida] could not locate main WMPF process")
|
||||||
|
|
||||||
pid_counts = Counter(wmpf_ppids)
|
proc_path = main_proc.parameters.get("path", "")
|
||||||
wmpf_pid = pid_counts.most_common(1)[0][0]
|
nums = re.findall(r"\d+", proc_path)
|
||||||
|
if not nums:
|
||||||
|
raise RuntimeError("[frida] cannot detect WMPF version from path")
|
||||||
|
version = int(nums[-1])
|
||||||
|
if version == 0:
|
||||||
|
raise RuntimeError("[frida] invalid WMPF version")
|
||||||
|
|
||||||
if wmpf_pid == 0:
|
return [main_pid], version
|
||||||
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
|
|
||||||
|
|
||||||
wmpf_process = None
|
def _find_wmpf_pids_darwin(self):
|
||||||
for p in processes:
|
"""macOS: find WeChatAppEx PIDs via pgrep, version via Info.plist."""
|
||||||
if p.pid == wmpf_pid:
|
try:
|
||||||
wmpf_process = p
|
out = subprocess.check_output(
|
||||||
break
|
["pgrep", "-f", "/MacOS/WeChatAppEx.app/Contents/MacOS/WeChatAppEx"],
|
||||||
|
text=True,
|
||||||
|
).strip()
|
||||||
|
pids = [int(p) for p in out.splitlines() if p.strip()]
|
||||||
|
except (subprocess.CalledProcessError, ValueError):
|
||||||
|
pids = []
|
||||||
|
if not pids:
|
||||||
|
raise RuntimeError("[frida] WeChatAppEx process not found on macOS")
|
||||||
|
|
||||||
if wmpf_process is None:
|
try:
|
||||||
raise RuntimeError("[frida] Could not find main WMPF process")
|
ver_out = subprocess.check_output(
|
||||||
|
["defaults", "read",
|
||||||
|
"/Applications/WeChat.app/Contents/MacOS/WeChatAppEx.app/Contents/Info.plist",
|
||||||
|
"CFBundleVersion"],
|
||||||
|
text=True,
|
||||||
|
).strip()
|
||||||
|
version = int(ver_out.split(".")[1])
|
||||||
|
except Exception:
|
||||||
|
raise RuntimeError("[frida] cannot detect WeChatAppEx version from Info.plist")
|
||||||
|
|
||||||
wmpf_process_path = wmpf_process.parameters.get("path", "")
|
return pids, version
|
||||||
version_matches = re.findall(r"\d+", wmpf_process_path)
|
|
||||||
if not version_matches:
|
|
||||||
raise RuntimeError("[frida] error in find wmpf version")
|
|
||||||
wmpf_version = int(version_matches[-1])
|
|
||||||
if wmpf_version == 0:
|
|
||||||
raise RuntimeError("[frida] error in find wmpf version")
|
|
||||||
|
|
||||||
session = device.attach(wmpf_pid)
|
async def _start_frida(self):
|
||||||
|
logger = self.logger
|
||||||
|
is_mac = sys.platform == "darwin"
|
||||||
|
platform_dir = "mac" if is_mac else "win"
|
||||||
|
|
||||||
if getattr(sys, 'frozen', False):
|
# Find PIDs and version
|
||||||
# PyInstaller onefile: resources in _MEIPASS; onedir: next to exe
|
if is_mac:
|
||||||
project_root = Path(getattr(sys, '_MEIPASS', Path(sys.executable).parent)).resolve()
|
pids, wmpf_version = self._find_wmpf_pids_darwin()
|
||||||
else:
|
else:
|
||||||
project_root = Path(__file__).parent.parent.resolve()
|
pids, wmpf_version = self._find_wmpf_pids_win()
|
||||||
|
|
||||||
|
# Load hook script and config
|
||||||
|
project_root = self._get_project_root()
|
||||||
hook_path = project_root / "frida" / "hook.js"
|
hook_path = project_root / "frida" / "hook.js"
|
||||||
if not hook_path.exists():
|
if not hook_path.exists():
|
||||||
raise RuntimeError("[frida] hook script not found")
|
raise RuntimeError("[frida] hook script not found")
|
||||||
script_content = hook_path.read_text(encoding="utf-8")
|
|
||||||
|
|
||||||
config_path = project_root / "frida" / "config" / f"addresses.{wmpf_version}.json"
|
config_path = project_root / "frida" / "config" / platform_dir / f"addresses.{wmpf_version}.json"
|
||||||
if not config_path.exists():
|
if not config_path.exists():
|
||||||
raise RuntimeError(f"[frida] version config not found: {wmpf_version}")
|
raise RuntimeError(f"[frida] version config not found: {platform_dir}/{wmpf_version}")
|
||||||
config_content = config_path.read_text(encoding="utf-8")
|
|
||||||
config_content = json.dumps(json.loads(config_content))
|
|
||||||
|
|
||||||
|
script_content = hook_path.read_text(encoding="utf-8")
|
||||||
|
config_content = json.dumps(json.loads(config_path.read_text(encoding="utf-8")))
|
||||||
final_script = script_content.replace("@@CONFIG@@", config_content)
|
final_script = script_content.replace("@@CONFIG@@", config_content)
|
||||||
script = session.create_script(final_script)
|
|
||||||
|
# Inject into all target PIDs
|
||||||
|
device = frida.get_local_device()
|
||||||
|
session = None
|
||||||
|
script = None
|
||||||
|
|
||||||
def on_message(message, data):
|
def on_message(message, data):
|
||||||
if message.get("type") == "error":
|
if message.get("type") == "error":
|
||||||
@@ -501,10 +532,22 @@ class DebugEngine:
|
|||||||
return
|
return
|
||||||
logger.frida_debug("[frida client]", message.get("payload", ""))
|
logger.frida_debug("[frida client]", message.get("payload", ""))
|
||||||
|
|
||||||
script.on("message", on_message)
|
for pid in pids:
|
||||||
script.load()
|
try:
|
||||||
|
s = device.attach(pid)
|
||||||
|
sc = s.create_script(final_script)
|
||||||
|
sc.on("message", on_message)
|
||||||
|
sc.load()
|
||||||
|
logger.info(f"[frida] injected pid={pid}, version={wmpf_version}")
|
||||||
|
# Keep first successful session/script as primary
|
||||||
|
if session is None:
|
||||||
|
session, script = s, sc
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[frida] failed to inject pid={pid}: {e}")
|
||||||
|
|
||||||
logger.info(f"[frida] script loaded, WMPF version: {wmpf_version}, pid: {wmpf_pid}")
|
if session is None:
|
||||||
|
raise RuntimeError("[frida] failed to inject any WeChatAppEx process")
|
||||||
|
|
||||||
|
logger.info(f"[frida] ready ({platform_dir}), version={wmpf_version}, {len(pids)} process(es)")
|
||||||
logger.info("[frida] you can now open any miniapps")
|
logger.info("[frida] you can now open any miniapps")
|
||||||
|
|
||||||
return session, script
|
return session, script
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
"""
|
r"""
|
||||||
extractor.py — 敏感信息提取引擎
|
extractor.py — 敏感信息提取引擎
|
||||||
直接使用 heartk_fast.py 的完整正则规则,保证提取结果一致
|
直接使用 heartk_fast.py 的完整正则规则,保证提取结果一致
|
||||||
支持自定义正则规则,自定义类别会出现在导出报告中
|
支持自定义正则规则,自定义类别会出现在导出报告中
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+28
-9
@@ -210,14 +210,33 @@ def find_wxapkg_files(packages_dir: str) -> List[dict]:
|
|||||||
|
|
||||||
|
|
||||||
def get_default_packages_dir() -> Optional[str]:
|
def get_default_packages_dir() -> Optional[str]:
|
||||||
"""获取默认的微信小程序包路径(Windows)"""
|
"""获取默认的微信小程序包路径(Windows / macOS)"""
|
||||||
if os.name != "nt":
|
import sys
|
||||||
return None
|
|
||||||
user_home = os.path.expanduser("~")
|
user_home = os.path.expanduser("~")
|
||||||
pkg_dir = os.path.join(
|
if sys.platform == "darwin":
|
||||||
user_home, "AppData", "Roaming", "Tencent",
|
# macOS: ~/Library/Containers/com.tencent.xinWeChat/Data/Documents/app_data/radium/users/{wxid}/applet/packages
|
||||||
"xwechat", "radium", "Applet", "packages"
|
users_dir = os.path.join(
|
||||||
)
|
user_home, "Library", "Containers", "com.tencent.xinWeChat",
|
||||||
if os.path.isdir(pkg_dir):
|
"Data", "Documents", "app_data", "radium", "users"
|
||||||
return pkg_dir
|
)
|
||||||
|
if not os.path.isdir(users_dir):
|
||||||
|
return None
|
||||||
|
# 找最近修改的用户目录
|
||||||
|
user_dirs = [
|
||||||
|
os.path.join(users_dir, d)
|
||||||
|
for d in os.listdir(users_dir)
|
||||||
|
if os.path.isdir(os.path.join(users_dir, d)) and not d.startswith(".")
|
||||||
|
]
|
||||||
|
for ud in sorted(user_dirs, key=os.path.getmtime, reverse=True):
|
||||||
|
pkg_dir = os.path.join(ud, "applet", "packages")
|
||||||
|
if os.path.isdir(pkg_dir):
|
||||||
|
return pkg_dir
|
||||||
|
return None
|
||||||
|
elif os.name == "nt":
|
||||||
|
pkg_dir = os.path.join(
|
||||||
|
user_home, "AppData", "Roaming", "Tencent",
|
||||||
|
"xwechat", "radium", "Applet", "packages"
|
||||||
|
)
|
||||||
|
if os.path.isdir(pkg_dir):
|
||||||
|
return pkg_dir
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
// ==UserScript==
|
|
||||||
// @name Bypass_Debugger
|
|
||||||
// @namespace https://github.com/0xsdeo/Bypass_Debugger
|
|
||||||
// @version 2024-12-06
|
|
||||||
// @description Bypass new Function --> debugger && constructor --> debugger && eval --> debugger
|
|
||||||
// @author 0xsdeo
|
|
||||||
// @match http://*/*
|
|
||||||
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
|
|
||||||
// @grant none
|
|
||||||
// @run-at document-start
|
|
||||||
// ==/UserScript==
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
globalThis.__INJECTED__ = true;
|
|
||||||
|
|
||||||
// eval may not exist in WeChat miniapp context
|
|
||||||
if (typeof eval !== 'undefined') {
|
|
||||||
try {
|
|
||||||
let temp_eval = eval;
|
|
||||||
window.eval = function () {
|
|
||||||
if (typeof arguments[0] == "string") {
|
|
||||||
arguments[0] = arguments[0].replaceAll(/debugger/g, '');
|
|
||||||
}
|
|
||||||
return temp_eval(...arguments);
|
|
||||||
}
|
|
||||||
} catch(e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
let OrigFunction = Function;
|
|
||||||
|
|
||||||
let NewFunction = function () {
|
|
||||||
for (let i = 0; i < arguments.length; i++) {
|
|
||||||
if (typeof arguments[i] == "string") {
|
|
||||||
arguments[i] = arguments[i].replaceAll(/debugger/g, '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OrigFunction(...arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to set prototype, skip if read-only (WeChat freezes Function)
|
|
||||||
try { NewFunction.prototype = OrigFunction.prototype; } catch(e) {}
|
|
||||||
try {
|
|
||||||
NewFunction.prototype.constructor = function () {
|
|
||||||
for (let i = 0; i < arguments.length; i++) {
|
|
||||||
if (typeof arguments[i] == "string") {
|
|
||||||
arguments[i] = arguments[i].replaceAll(/debugger/g, '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OrigFunction(...arguments);
|
|
||||||
}
|
|
||||||
NewFunction.prototype.constructor.prototype = NewFunction.prototype;
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
// Replace global Function
|
|
||||||
try { window.Function = NewFunction; } catch(e) {}
|
|
||||||
try { globalThis.Function = NewFunction; } catch(e) {}
|
|
||||||
try { Object.freeze(NewFunction); } catch(e) {}
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
// Also patch setTimeout/setInterval which can take string arguments with debugger
|
|
||||||
try {
|
|
||||||
let origSetTimeout = setTimeout;
|
|
||||||
window.setTimeout = function(fn, delay) {
|
|
||||||
if (typeof fn === 'string') {
|
|
||||||
fn = fn.replaceAll(/debugger/g, '');
|
|
||||||
}
|
|
||||||
return origSetTimeout.apply(this, arguments);
|
|
||||||
};
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
let origSetInterval = setInterval;
|
|
||||||
window.setInterval = function(fn, delay) {
|
|
||||||
if (typeof fn === 'string') {
|
|
||||||
fn = fn.replaceAll(/debugger/g, '');
|
|
||||||
}
|
|
||||||
return origSetInterval.apply(this, arguments);
|
|
||||||
};
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
console.log('[Bypass_Debugger] hooks installed');
|
|
||||||
window.__BYPASS_DEBUGGER__ = true;
|
|
||||||
Object.freeze(Function);
|
|
||||||
})();
|
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 2
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "first"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "frida" },
|
||||||
|
{ name = "protobuf" },
|
||||||
|
{ name = "pycryptodome" },
|
||||||
|
{ name = "pyside6" },
|
||||||
|
{ name = "websockets" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "frida", specifier = ">=17.0.0" },
|
||||||
|
{ name = "protobuf", specifier = ">=4.0.0" },
|
||||||
|
{ name = "pycryptodome" },
|
||||||
|
{ name = "pyside6", specifier = ">=6.5.0" },
|
||||||
|
{ name = "websockets", specifier = ">=12.0" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "frida"
|
||||||
|
version = "17.9.3"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/c9/f4e98eaca54bf2f52dad0e6ce532e72bb556c4e54b7d2cd111ac48a9014e/frida-17.9.3.tar.gz", hash = "sha256:cf81bbb3e8901ec2dff1d74aaf2e1b2be10ca602a040fb2ef1ffd8300ffdaf3c", size = 927621, upload-time = "2026-04-28T15:55:41.574Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/e0/8c125a8ee554bc9bc2217ffcaad359402ca4e431c11da82c440214dc4186/frida-17.9.3-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:535df74837d12873d10b7c7445febea75968e7f02a84042e4c32261d7c08328c", size = 22878819, upload-time = "2026-04-28T15:55:00.169Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/b2/f0971159443fbb2acc776a1dd520b0455e4d373572917912007c98ad8834/frida-17.9.3-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:d37eca0d3425d3de0998c5c028c64765f55c482b292dfd1fb00baf6c1326bf59", size = 32253853, upload-time = "2026-04-28T15:55:05.152Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/fd/64a5e77f1539e53f4d3d87532d43a65e6d539415ce886b0686ccdcb1d9cd/frida-17.9.3-cp37-abi3-manylinux1_i686.whl", hash = "sha256:92ebe2d351adbf1fe17f4dfeb81dd2cbdf896722e45839e8a256b37b6d4ee5c1", size = 20688476, upload-time = "2026-04-28T15:55:08.855Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/6c/807b1c03b309d0f4a4ddd31492323bf97173d67c2296477cffc34cbbe67d/frida-17.9.3-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:2f947a55e470e105c699f26f1f0a324e1747959c83b4f2f8f110a4698a83eac8", size = 32917515, upload-time = "2026-04-28T15:55:11.588Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/86/7232cdc26f7bcbb5006049996687faf89bb526b100833791bc57d5c0c355/frida-17.9.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:0e3bca26c6b9accb2374f5cc8fb2b7ea7fc9be538228497ca5660111fb85ed2a", size = 21497450, upload-time = "2026-04-28T15:55:14.548Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/3a/99b55f0790cf6c4babc26eeb189a9aa83968c8b909d83540d0ce952b9390/frida-17.9.3-cp37-abi3-manylinux2014_armv7l.whl", hash = "sha256:5ae96e22dee0219b3361f37b34e5b65d23818282aa603e416451c1ff2a637f67", size = 19335314, upload-time = "2026-04-28T15:55:17.457Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/7a/770f6c54a21fc0e7858045459b953beb64234046275b1e62148fd0e07c92/frida-17.9.3-cp37-abi3-manylinux_2_17_aarch64.whl", hash = "sha256:5843b4e1cb14e5ef8405e95d747202d2d9c6459ea1a7c78287e46d186dd8530f", size = 21497451, upload-time = "2026-04-28T15:55:20.274Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/a2/fa94990bb6df6a5bf0a4ab2c2a9d54e273934813bfb3b3c78bb6aa1b4959/frida-17.9.3-cp37-abi3-manylinux_2_17_armv7l.whl", hash = "sha256:43d7ec9d33de2837447fb13516c25683bfac19f683a52b36e42a34735eb54f7f", size = 19335314, upload-time = "2026-04-28T15:55:23.012Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/47/e26468826287b2463b0513448f32d8bbb9700ee3ed6dca41445ecdc95828/frida-17.9.3-cp37-abi3-manylinux_2_5_i686.whl", hash = "sha256:ed8af3db918918d4954e9892217fbbafef93a65ed2d41cf07aed494cc4b9f64b", size = 20688481, upload-time = "2026-04-28T15:55:25.475Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/8e/cd/3c11f8c301bff714fbda8cb00c3578af2a1b6d8d525b5a93f7058eba592e/frida-17.9.3-cp37-abi3-manylinux_2_5_x86_64.whl", hash = "sha256:25265b0591db9ff2b8639bba7698338a4065cf2bdc82f7a14a12689731a1da91", size = 32917520, upload-time = "2026-04-28T15:55:28.22Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/c0/7948bc65b7a33f4d103d5d99ab55066c1ef65345bad0e2404a4b3d7b0a71/frida-17.9.3-cp37-abi3-win32.whl", hash = "sha256:21f5bed08c266ee1144c7bef3171f43b63daa165bbd19296dd7d84b32782e440", size = 39317027, upload-time = "2026-04-28T15:55:31.516Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/33/f65b00d07e2ac34850c26dd532713b4ad93f27d27cdb546165cfa0dade21/frida-17.9.3-cp37-abi3-win_amd64.whl", hash = "sha256:694848b1517d6304cc634516ee8228a9b40f129afb79f632bf97b0174d650b0d", size = 41961019, upload-time = "2026-04-28T15:55:35.059Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/d6/927ad688c2bfc0e4c87d63222e99dad691a4da9ed4e2184851025aa43f5e/frida-17.9.3-cp37-abi3-win_arm64.whl", hash = "sha256:3be3b85fe0817ecfc8b7cd0dee0ed8c4dee4ede25cf7ec02ff6118dbe1156ae1", size = 51849086, upload-time = "2026-04-28T15:55:38.629Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "protobuf"
|
||||||
|
version = "7.34.1"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/6b/a0e95cad1ad7cc3f2c6821fcab91671bd5b78bd42afb357bb4765f29bc41/protobuf-7.34.1.tar.gz", hash = "sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280", size = 454708, upload-time = "2026-03-20T17:34:47.036Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7", size = 429247, upload-time = "2026-03-20T17:34:37.024Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/9d/aa69df2724ff63efa6f72307b483ce0827f4347cc6d6df24b59e26659fef/protobuf-7.34.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b", size = 325753, upload-time = "2026-03-20T17:34:38.751Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/e8/d174c91fd48e50101943f042b09af9029064810b734e4160bbe282fa1caa/protobuf-7.34.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a", size = 340198, upload-time = "2026-03-20T17:34:39.871Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4", size = 324267, upload-time = "2026-03-20T17:34:41.1Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/29/64de04a0ac142fb685fd09999bc3d337943fb386f3a0ec57f92fd8203f97/protobuf-7.34.1-cp310-abi3-win32.whl", hash = "sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a", size = 426628, upload-time = "2026-03-20T17:34:42.536Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/87/cb5e585192a22b8bd457df5a2c16a75ea0db9674c3a0a39fc9347d84e075/protobuf-7.34.1-cp310-abi3-win_amd64.whl", hash = "sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c", size = 437901, upload-time = "2026-03-20T17:34:44.112Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/95/608f665226bca68b736b79e457fded9a2a38c4f4379a4a7614303d9db3bc/protobuf-7.34.1-py3-none-any.whl", hash = "sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11", size = 170715, upload-time = "2026-03-20T17:34:45.384Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pycryptodome"
|
||||||
|
version = "3.23.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/12/e33935a0709c07de084d7d58d330ec3f4daf7910a18e77937affdb728452/pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379", size = 1623886, upload-time = "2025-05-17T17:21:20.614Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/0b/aa8f9419f25870889bebf0b26b223c6986652bdf071f000623df11212c90/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4", size = 1672151, upload-time = "2025-05-17T17:21:22.666Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/5e/63f5cbde2342b7f70a39e591dbe75d9809d6338ce0b07c10406f1a140cdc/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630", size = 1664461, upload-time = "2025-05-17T17:21:25.225Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/92/608fbdad566ebe499297a86aae5f2a5263818ceeecd16733006f1600403c/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353", size = 1702440, upload-time = "2025-05-17T17:21:27.991Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/92/2eadd1341abd2989cce2e2740b4423608ee2014acb8110438244ee97d7ff/pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5", size = 1803005, upload-time = "2025-05-17T17:21:31.37Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyside6"
|
||||||
|
version = "6.11.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pyside6-addons" },
|
||||||
|
{ name = "pyside6-essentials" },
|
||||||
|
{ name = "shiboken6" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/95/f3f5a2799163b6658126d78a85bc1dec9eda88c75c26780556b26071a1d8/pyside6-6.11.0-cp310-abi3-macosx_13_0_universal2.whl", hash = "sha256:1f2735dc4f2bd4ec452ae50502c8a22128bba0aced35358a2bbc58384b820c6f", size = 571544, upload-time = "2026-03-23T12:47:20.263Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/89/9a1f521051714e6694ebbe2b979ded279845ec8e25cb309ca3960158d74f/pyside6-6.11.0-cp310-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c642e2d25704ca746fd37f56feacf25c5aecc4cd40bef23d18eec81f87d9dc00", size = 571725, upload-time = "2026-03-23T12:47:21.727Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/3d/f779d8bba00fcde31a7d7fb6b59347a70773c9cc8135592dea9972579877/pyside6-6.11.0-cp310-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:267b344c73580ac938ca63c611881fb42a3922ebfe043e271005f4f06c372c4e", size = 571722, upload-time = "2026-03-23T12:47:22.761Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/98/150e01a026df3e9697310236821fa825319bb4b9d6137539cb25a3032968/pyside6-6.11.0-cp310-abi3-win_amd64.whl", hash = "sha256:9092cb002ca43c64006afb2e0d0f6f51aef17aa737c33a45e502326a081ddcbc", size = 577988, upload-time = "2026-03-23T12:47:23.795Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/e7/55960f7c6b41d058e95cb4af02652c46c48702c506c8bbf12e99550e1fb3/pyside6-6.11.0-cp310-abi3-win_arm64.whl", hash = "sha256:b15f39acc2b8f46251a630acad0d97f9a0a0461f2baffcd66d7adfada8eb641e", size = 561372, upload-time = "2026-03-23T12:47:25.073Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyside6-addons"
|
||||||
|
version = "6.11.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pyside6-essentials" },
|
||||||
|
{ name = "shiboken6" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/df/241f311c61a46b7b1195927da77b2537692ee3442aa9ccd87981164ff78d/pyside6_addons-6.11.0-cp310-abi3-macosx_13_0_universal2.whl", hash = "sha256:d5eaa4643302e3a0fa94c5766234bee4073d7d5ab9c2b7fd222692a176faf182", size = 331554157, upload-time = "2026-03-23T12:40:40.497Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/b9/e81172835ccc9d8b9792cc6bf7524a252a0db9a76ddd693de230402697f9/pyside6_addons-6.11.0-cp310-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ac6fe3d4ef4497dde3efc5e896b0acd53ff6c93be4bf485f045690f919419f35", size = 174948482, upload-time = "2026-03-23T12:41:05.379Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/a4/426d9333782bf65ab2a20257d6b4b3af9b8d5d7a710da719865fab49d492/pyside6_addons-6.11.0-cp310-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:8ffb40222456078930816ebcac2f2511716d2acbc11716dd5acc5c365179a753", size = 170430798, upload-time = "2026-03-23T12:41:38.134Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/9a/46d271fedfabad8c6dce2ebb69bb593745487ed33753a56a47c3ba4fdb1c/pyside6_addons-6.11.0-cp310-abi3-win_amd64.whl", hash = "sha256:413e6121c24f5ffdce376298059eddecff74aa6d638e94e0f6015b33d29b889e", size = 168723088, upload-time = "2026-03-23T12:42:00.668Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/cd/1b28264f7dc9a642da2e4e7c02f67418d0949eb7ce329ae20869703c2630/pyside6_addons-6.11.0-cp310-abi3-win_arm64.whl", hash = "sha256:aaaee83385977a0fe134b2f4fbfb92b45a880d5b656e4d90a708eef10b1b6de8", size = 35698324, upload-time = "2026-03-23T12:42:13.748Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyside6-essentials"
|
||||||
|
version = "6.11.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "shiboken6" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/00/8a8583d3429c737cc20e61a43eba8ab1ec13ddb101e99802c2ffeedf3b41/pyside6_essentials-6.11.0-cp310-abi3-macosx_13_0_universal2.whl", hash = "sha256:85d6ca87ef35fa6565d385ede72ae48420dd3f63113929d10fc800f6b0360e01", size = 108085251, upload-time = "2026-03-23T12:42:52.872Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/a9/07c9e5c014b871c1b19caf8f994bcd50b345559b81f81671217b49559b67/pyside6_essentials-6.11.0-cp310-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:dc20e7afd5fc6fe51297db91cef997ce60844be578f7a49fc61b7ab9657a8849", size = 78316055, upload-time = "2026-03-23T12:43:04.19Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/35/f06b1b641d7600ec46374c16cd37c66fa4a22870326b4eb073a95471035f/pyside6_essentials-6.11.0-cp310-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:4854cb0a1b061e7a576d8fb7bb7cf9f49540d558b1acb7df0742a7afefe61e4e", size = 77380821, upload-time = "2026-03-23T12:43:24.649Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/37/ba95c6262836d2b286b4e05a9d16a5e870995d5d2503ac6adc6312208049/pyside6_essentials-6.11.0-cp310-abi3-win_amd64.whl", hash = "sha256:3b3362882ad9389357a80504e600180006a957731fec05786fced7b038461fdf", size = 75793322, upload-time = "2026-03-23T12:43:35.575Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/27/d17f25e45820e633a70e6109b35991eda09a5e8000c2a306f0ab7538d48c/pyside6_essentials-6.11.0-cp310-abi3-win_arm64.whl", hash = "sha256:81ca603dbf21bc39f89bb42db215c25ebe0c879a1a4c387625c321d2730ec187", size = 56337457, upload-time = "2026-03-23T12:43:43.573Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shiboken6"
|
||||||
|
version = "6.11.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/1d/b56b7b694fbc871496435488d1f41c5068de546334850d722756511cef65/shiboken6-6.11.0-cp310-abi3-macosx_13_0_universal2.whl", hash = "sha256:d88e8a1eb705f2b9ad21db08a61ae1dc0c773e5cd86a069de0754c4cf1f9b43b", size = 476085, upload-time = "2026-03-23T12:47:05.724Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/cb/4bb0c76011166230daa7c0074aeb3fdb3935c83ac1fef3789b85fcd1a8fc/shiboken6-6.11.0-cp310-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ad54e64f8192ddbdff0c54ac82b89edcd62ed623f502ea21c960541d19514053", size = 271055, upload-time = "2026-03-23T12:47:07.349Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/96/771a6e2b530f725303d16d78a321fa4876b98b4f3615c9851880df8c1a43/shiboken6-6.11.0-cp310-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:a10dc7718104ea2dc15d5b0b96909b77162ce1c76fcc6968e6df692b947a00e9", size = 267456, upload-time = "2026-03-23T12:47:08.689Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/f7/44c0c42c3f5f29dec457fd46ea0552174bcb8aa75becf03bbd90308ba07b/shiboken6-6.11.0-cp310-abi3-win_amd64.whl", hash = "sha256:483ff78a73c7b3189ca924abc694318084f078bcfeaffa68e32024ff2d025ee1", size = 1222132, upload-time = "2026-03-23T12:47:10.143Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/99/6e5ee21db2d6af84bbbd7d871d441dafeb069c6de5667b1aa49891a77c66/shiboken6-6.11.0-cp310-abi3-win_arm64.whl", hash = "sha256:3bd76cf56105ab2d62ecaff630366f11264f69b88d488f10f048da9a065781f4", size = 1783186, upload-time = "2026-03-23T12:47:11.832Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.15.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "websockets"
|
||||||
|
version = "16.0"
|
||||||
|
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
|
||||||
|
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021, upload-time = "2026-01-10T09:22:22.696Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320, upload-time = "2026-01-10T09:22:23.94Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815, upload-time = "2026-01-10T09:22:25.469Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054, upload-time = "2026-01-10T09:22:27.101Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565, upload-time = "2026-01-10T09:22:28.293Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848, upload-time = "2026-01-10T09:22:30.394Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249, upload-time = "2026-01-10T09:22:32.083Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685, upload-time = "2026-01-10T09:22:33.345Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340, upload-time = "2026-01-10T09:22:34.539Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022, upload-time = "2026-01-10T09:22:36.332Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319, upload-time = "2026-01-10T09:22:37.602Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631, upload-time = "2026-01-10T09:22:38.789Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870, upload-time = "2026-01-10T09:22:39.893Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361, upload-time = "2026-01-10T09:22:41.016Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615, upload-time = "2026-01-10T09:22:42.442Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246, upload-time = "2026-01-10T09:22:43.654Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684, upload-time = "2026-01-10T09:22:44.941Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947, upload-time = "2026-01-10T09:23:36.166Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260, upload-time = "2026-01-10T09:23:37.409Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071, upload-time = "2026-01-10T09:23:39.158Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968, upload-time = "2026-01-10T09:23:41.031Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735, upload-time = "2026-01-10T09:23:42.259Z" },
|
||||||
|
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" },
|
||||||
|
]
|
||||||
@@ -1,48 +1,119 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
title Launcher
|
chcp 437 >nul
|
||||||
|
title First - Launcher
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
:: Skip dependency check if already installed before
|
set "CHOICE_FILE=.launch_choice"
|
||||||
if exist ".deps_installed" goto :launch
|
|
||||||
|
|
||||||
:: Check if requirements.txt exists
|
:: ══════════════════════════════════════════
|
||||||
if not exist "requirements.txt" (
|
:: Read saved choice and launch directly
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
if exist "%CHOICE_FILE%" (
|
||||||
|
set /p SAVED=<"%CHOICE_FILE%"
|
||||||
|
if "!SAVED!"=="uv" goto :RUN_UV
|
||||||
|
if "!SAVED!"=="system" goto :RUN_SYSTEM
|
||||||
|
)
|
||||||
|
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
:: First run: ask user to choose environment
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
echo.
|
||||||
|
echo ============================================
|
||||||
|
echo First ^| Launch Configuration
|
||||||
|
echo ============================================
|
||||||
|
echo.
|
||||||
|
echo Please choose how to run First:
|
||||||
|
echo.
|
||||||
|
echo [1] uv virtual environment (Recommended)
|
||||||
|
echo Isolated dependencies, won't affect system Python
|
||||||
|
echo.
|
||||||
|
echo [2] System Python
|
||||||
|
echo Use system-installed Python directly
|
||||||
|
echo.
|
||||||
|
set /p CHOICE=" Enter choice (1/2): "
|
||||||
|
|
||||||
|
if "%CHOICE%"=="1" goto :SETUP_UV
|
||||||
|
if "%CHOICE%"=="2" goto :SETUP_SYSTEM
|
||||||
|
echo Invalid choice. Exiting.
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
:: Branch: uv virtual environment
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
:SETUP_UV
|
||||||
|
where uv >nul 2>nul
|
||||||
|
if errorlevel 1 (
|
||||||
echo.
|
echo.
|
||||||
echo [WARNING] requirements.txt not found!
|
echo [WARNING] uv not found on this system.
|
||||||
echo.
|
echo.
|
||||||
set /p "choice= Skip dependency install and launch directly? [Y/N]: "
|
set /p INSTALLUV=" Install uv now? (pip install uv) [Y/N]: "
|
||||||
|
if /i "!INSTALLUV!"=="Y" (
|
||||||
|
echo Installing uv...
|
||||||
|
pip install uv
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [ERROR] uv installation failed. Please run manually: pip install uv
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo Cancelled.
|
||||||
|
pause
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
:RUN_UV
|
||||||
|
echo.
|
||||||
|
echo Syncing uv virtual environment...
|
||||||
|
echo.
|
||||||
|
uv sync -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
if errorlevel 1 (
|
||||||
echo.
|
echo.
|
||||||
if /i "!choice!"=="Y" goto :launch
|
echo [ERROR] uv sync failed. Check network or pyproject.toml.
|
||||||
echo Cancelled.
|
pause
|
||||||
timeout /t 2 >nul
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo uv>"%CHOICE_FILE%"
|
||||||
|
start "" ".venv\Scripts\pythonw.exe" gui.py
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
:: Branch: System Python
|
||||||
|
:: ══════════════════════════════════════════
|
||||||
|
:SETUP_SYSTEM
|
||||||
|
where python >nul 2>nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo.
|
||||||
|
echo [ERROR] python not found. Please install Python 3.9+ first.
|
||||||
|
pause
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
:: requirements.txt found, ask to install
|
|
||||||
echo.
|
echo.
|
||||||
echo [OK] requirements.txt found.
|
echo Checking dependencies...
|
||||||
echo.
|
python -c "import frida, websockets, google.protobuf, PySide6, Crypto" >nul 2>nul
|
||||||
set /p "install= Install dependencies? [Y/N]: "
|
if errorlevel 1 (
|
||||||
echo.
|
echo Some dependencies are missing.
|
||||||
if /i "!install!"=="Y" (
|
|
||||||
echo Installing via Tsinghua mirror, please wait...
|
|
||||||
echo.
|
echo.
|
||||||
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
set /p INSTALLDEPS=" Install dependencies now? (pip install -r requirements.txt) [Y/N]: "
|
||||||
if errorlevel 1 (
|
if /i "!INSTALLDEPS!"=="Y" (
|
||||||
echo.
|
echo Installing dependencies...
|
||||||
echo [ERROR] Installation failed! Check your network or pip config.
|
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [ERROR] Installation failed. Try manually: pip install -r requirements.txt
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo Cancelled.
|
||||||
pause
|
pause
|
||||||
exit /b 1
|
exit /b 0
|
||||||
)
|
)
|
||||||
echo.
|
|
||||||
echo [OK] Done! Will skip this step on next launch.
|
|
||||||
echo. > .deps_installed
|
|
||||||
echo.
|
|
||||||
) else (
|
|
||||||
echo. > .deps_installed
|
|
||||||
)
|
)
|
||||||
|
|
||||||
:: Launch gui.py without command window
|
:RUN_SYSTEM
|
||||||
:launch
|
echo system>"%CHOICE_FILE%"
|
||||||
start "" pythonw gui.py
|
start "" pythonw gui.py
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# ── 配置文件路径 ──
|
||||||
|
CHOICE_FILE=".launch_choice"
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
# 对话框工具(macOS 用 osascript,Linux 降级为 read)
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
dialog_choice() {
|
||||||
|
# $1=标题 $2=提示文字 $3=按钮1 $4=按钮2
|
||||||
|
# 返回 0 = 按钮1,1 = 按钮2
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
local btn
|
||||||
|
btn=$(osascript -e "button returned of (display dialog \"$2\" with title \"$1\" buttons {\"$4\", \"$3\"} default button \"$3\")" 2>/dev/null)
|
||||||
|
[[ "$btn" == "$3" ]] && return 0 || return 1
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo " $1"
|
||||||
|
echo " $2"
|
||||||
|
echo " [1] $3 [2] $4"
|
||||||
|
read -rp " 请输入选择 (1/2): " sel
|
||||||
|
[[ "$sel" == "1" ]] && return 0 || return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_info() {
|
||||||
|
# $1=标题 $2=内容
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
osascript -e "display dialog \"$2\" with title \"$1\" buttons {\"确定\"} default button \"确定\"" >/dev/null 2>&1
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo " [$1] $2"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
# 读取上次选择
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
if [[ -f "$CHOICE_FILE" ]]; then
|
||||||
|
SAVED=$(cat "$CHOICE_FILE")
|
||||||
|
# 直接按上次结果启动
|
||||||
|
if [[ "$SAVED" == "uv" ]]; then
|
||||||
|
echo " [启动] 使用 uv 虚拟环境..."
|
||||||
|
uv sync -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
dialog_info "启动失败" "uv sync 失败,请检查网络或 uv 配置。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
.venv/bin/python gui.py &
|
||||||
|
exit 0
|
||||||
|
elif [[ "$SAVED" == "system" ]]; then
|
||||||
|
echo " [启动] 使用系统 Python..."
|
||||||
|
python3 gui.py &
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
# 首次运行:让用户选择环境
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
dialog_choice "First — 启动配置" \
|
||||||
|
"请选择运行方式:\n\n ✦ uv 虚拟环境(推荐)\n 自动隔离依赖,不影响系统 Python\n\n ✦ 系统 Python\n 使用系统已安装的 Python 直接运行" \
|
||||||
|
"uv 虚拟环境" "系统 Python"
|
||||||
|
USE_UV=$?
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
# 分支:uv 虚拟环境
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
if [[ $USE_UV -eq 0 ]]; then
|
||||||
|
|
||||||
|
# 检查 uv 是否已安装
|
||||||
|
if ! command -v uv >/dev/null 2>&1; then
|
||||||
|
dialog_choice "未找到 uv" \
|
||||||
|
"系统中未检测到 uv 工具。\n是否现在安装 uv?\n\n(将执行:pip install uv)" \
|
||||||
|
"安装 uv" "取消"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo " 正在安装 uv..."
|
||||||
|
pip install uv
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
dialog_info "安装失败" "uv 安装失败,请手动执行:pip install uv"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " 已取消。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " 正在同步 uv 虚拟环境..."
|
||||||
|
uv sync -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
dialog_info "同步失败" "uv sync 失败,请检查网络连接或 pyproject.toml 配置。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "uv" > "$CHOICE_FILE"
|
||||||
|
.venv/bin/python gui.py &
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
# 分支:系统 Python
|
||||||
|
# ══════════════════════════════════════════
|
||||||
|
else
|
||||||
|
|
||||||
|
# 检查 python3
|
||||||
|
if ! command -v python3 >/dev/null 2>&1; then
|
||||||
|
dialog_info "未找到 Python" "系统中未检测到 python3,请先安装 Python 3.9+。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查是否缺少依赖
|
||||||
|
MISSING=0
|
||||||
|
python3 -c "import frida, websockets, google.protobuf, PySide6, Crypto" 2>/dev/null || MISSING=1
|
||||||
|
|
||||||
|
if [[ $MISSING -eq 1 ]]; then
|
||||||
|
dialog_choice "缺少依赖库" \
|
||||||
|
"检测到部分依赖库未安装。\n是否现在安装?\n\n(将执行:pip install -r requirements.txt)" \
|
||||||
|
"立即安装" "取消"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo " 正在安装依赖..."
|
||||||
|
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
dialog_info "安装失败" "依赖安装失败,请检查网络或手动执行:\npip install -r requirements.txt"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " 已取消。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "system" > "$CHOICE_FILE"
|
||||||
|
python3 gui.py &
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user