Author SHA1 Message Date
牟不懂哎 02b58948a0 v1.0.8 2026-05-04 23:10:40 +08:00
牟不懂哎 797004582f v1.0.8 2026-05-04 23:07:44 +08:00
牟不懂哎 6e4a3b2464 Merge branch 'main' of https://github.com/Spade-sec/First 2026-05-04 23:05:28 +08:00
牟不懂哎 c2f668b9db v1.0.8 2026-05-04 23:03:28 +08:00
牟不懂哎 2940e15105 Merge pull request #11 from XiangXtreme/main
新增H5服务号支持调试功能,uv管理项目等功能
2026-05-01 20:28:09 +08:00
XiangXtreme 884d882eb7 init 2026-04-30 13:09:26 +08:00
牟不懂哎 b8bfac4641 v1.0.7 2026-04-22 19:40:29 +08:00
牟不懂哎 4a64e54935 v1.0.6 2026-04-19 15:11:59 +08:00
73 changed files with 1434 additions and 448 deletions
+4
View File
@@ -0,0 +1,4 @@
.venv/
.deps_installed
__pycache__/
*.py[cod]
+110 -42
View File
@@ -1,43 +1,47 @@
# First
> 微信小程序调试工具 —— 基于 Frida + CDP 代理,支持 GUI 与 CLI 双模式
> 微信小程序安全调试工具 —— 基于 Frida + CDP 代理,支持 Windows / macOS 双平台,GUI 与 CLI 双模式
---
本项目仅支持windows,macos用户使用pd虚拟机即可
## 截图预览
### 主界面 / Control Panel
### 主界面
![zhuyem](https://s1.galgame.fun/imgb/u0/20260408_69d655f49ca7e.png)
![主界面](https://s1.galgame.fun/imgb/u0/20260408_69d655f49ca7e.png)
### 路由导航
![luyou](https://s1.galgame.fun/imgb/u0/20260408_69d6560ca1a39.png)
![路由导航](https://s1.galgame.fun/imgb/u0/20260408_69d6560ca1a39.png)
### 云函数分析
![QQ20260402-192623](https://s1.galgame.fun/imgb/u0/20260402_69ce527ca5480.png)
### 调试开关(JSRPC 与调用 wx.cloud)
![调试](https://s1.galgame.fun/imgb/u0/20260408_69d6564195009.png)
![云函数分析](https://s1.galgame.fun/imgb/u0/20260402_69ce527ca5480.png)
### 调试开关(JSRPC / wx.cloud 调用)
![调试开关](https://s1.galgame.fun/imgb/u0/20260408_69d6564195009.png)
### 敏感信息提取
![PixPin_2026-04-16_18-45-08](https://s1.galgame.fun/imgb/u55/20260416_69e0be0e1c1d7.png)
![敏感信息提取-1](https://s1.galgame.fun/imgb/u55/20260416_69e0be0e1c1d7.png)
<img src="https://s1.galgame.fun/imgb/u55/20260416_69e0be0c38e39.png" alt="PixPin_2026-04-16_18-45-59" />
<img src="https://s1.galgame.fun/imgb/u55/20260416_69e0be0c38e39.png" alt="敏感信息提取-2" />
![PixPin_2026-04-16_18-45-52](https://s1.galgame.fun/imgb/u55/20260416_69e0be0c70d46.png)
![敏感信息提取-3](https://s1.galgame.fun/imgb/u55/20260416_69e0be0c70d46.png)
---
## 功能特性
- 通过 Frida 注入微信客户端,转发小程序调试协议
- CDP 代理桥接,支持 Chrome DevTools 直接连接调试
- 路由枚举与一键跳转导航
- 云函数调用监控与参数分析
- UserScript 自动注入(支持按 URL 匹配、run-at 时机控制)
- 内置安全扫描模块,生成扫描报告
- Frida 动态注入微信客户端,转发小程序调试协议
- CDP 代理桥接,Chrome DevTools 直连调试
- 路由枚举、分类与一键跳转
- 云函数调用监控与参数分析(动态 Hook + 静态扫描)
- UserScript 自动注入(支持 URL 匹配、run-at 时机控制)
- wxapkg 解密解包 + 敏感信息扫描(IP / 密钥 / 云存储 / JWT 等)
- 深色 / 浅色主题切换
- GUI(PySide6)与 CLI 双模式运行
- GUI(PySide6)与 CLI 双模式
---
@@ -50,6 +54,7 @@
| websockets | >= 12.0 |
| protobuf | >= 4.0.0 |
| PySide6 | >= 6.5.0 |
| pycryptodome | 最新版 |
安装依赖:
@@ -59,26 +64,45 @@ pip install -r requirements.txt
---
## 微信版本要求
## 支持的微信版本
- 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)
### 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)
### GUI 模式(推荐)
### 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
```
双击启动.bat
启动后在主界面点击 **启动调试** 即可开始调试。
### 小程序页面操作
### macOS
点击启动调试前请勿打开小程序, **启动调试**打开后再次启动**小程序**即可。
**一键启动:** 终端执行 `./启动.sh`,首次运行会自动安装依赖。
**手动启动:**
```bash
python3 gui.py
```
启动后在主界面点击 **启动调试**,然后再打开小程序即可(请勿在启动调试前打开小程序)。
### CLI 模式
@@ -92,6 +116,7 @@ python main.py --cdp-port 62000
# 开启详细日志
python main.py --debug-main --debug-frida
```
### 连接 Chrome DevTools
启动后,在 Chrome 地址栏输入:
@@ -100,7 +125,39 @@ python main.py --debug-main --debug-frida
devtools://devtools/bundled/inspector.html?ws=127.0.0.1:62000
```
### 参数说明
---
## 服务号调试操作
1. 打开一个小程序页面作为占位(保持不关闭)
2. 访问需要调试的服务号内容(如 H5 网页)
![PixPin_2026-05-04_22-48-42](https://s1.galgame.fun/imgb/u55/20260504_69f8b299a7d85.png)
3. 在工具栏「服务」目标列表中找到目标网页,双击后切换至调试视图即可开始调试
![PixPin_2026-05-04_22-51-14](https://s1.galgame.fun/imgb/u55/20260504_69f8b299a7d94.png)
![PixPin_2026-05-04_22-51-39](https://s1.galgame.fun/imgb/u55/20260504_69f8b299a804b.png)
---
## macOS 注意事项
如果 Frida 注入报错,需要解除系统对进程附加的限制,任选其一:
**方案一:关闭 SIP(系统完整性保护)**
> 关闭后 Frida 才能正常注入进程。参考教程:[macOS SIP 开启关闭教程](https://cloud.tencent.com/developer/article/1496058)
**方案二:强制重签名 WeChat**
```bash
sudo codesign --force --deep --sign - /Applications/WeChat.app
```
---
## 参数说明
| 参数 | 默认值 | 说明 |
|------|--------|------|
@@ -111,11 +168,11 @@ devtools://devtools/bundled/inspector.html?ws=127.0.0.1:62000
| `--scripts-dir` | `./userscripts` | UserScript 目录路径 |
| `--script` | — | 指定单个 .js 文件注入(可多次使用) |
### UserScript 注入
---
将 `.js` 脚本放入 `userscripts/` 目录,工具启动时自动加载并按规则注入。
## UserScript 注入
也可手动指定文件:
将 `.js` 脚本放入 `userscripts/` 目录,启动时自动加载并注入。也可手动指定:
```bash
python main.py --script ./my_hook.js --script ./another.js
@@ -131,21 +188,27 @@ pyinstaller WMPFDebugger.spec
---
## 常见问题解决办法
## 常见问题
1. Frida 已显示连接,但小程序端显示未连接或无法断点调试
**Q: Frida 已连接,但小程序端显示未连接或无法断点调试?**
若操作顺序无误,建议先彻底卸载微信并重启电脑(如有重要聊天记录请提前备份)。
删除路径C:\Users\用户名\AppData\Roaming\Tencent\xwechat\XPlugin\Plugins\RadiumWMPF下所有以数字命名的文件夹,再次重启电脑后,安装微信 4.1.0.30 版本。安装完成后检查上述路径,确认文件夹编号为 16389。
确认操作顺序无误后,尝试以下步骤:
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)
- [进击的HACK / JSRPC 与调用 wx.cloud](https://mp.weixin.qq.com/s/hTlekrCPiMJCvsHYx7CAxw)
- [linguo2625469/WMPFDebugger-mac](https://github.com/linguo2625469/WMPFDebugger-mac)
---
## 致谢
@@ -153,9 +216,14 @@ pyinstaller WMPFDebugger.spec
感谢 **0xsdeo** 师傅的大力支持与思路提供。
---
## 交流群
群满200变成手动挡了。加我拉
![1db5b1b2699ae709a191207cf97dcf4b](https://s1.galgame.fun/imgb/u55/20260413_69dcaf1310fc4.jpg)
群满 200 人后需要手动邀请,请加我拉群:
![微信二维码](https://s1.galgame.fun/imgb/u55/20260413_69dcaf1310fc4.jpg)
---
## 免责声明
+19
View File
@@ -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
}
}
}
+20
View File
@@ -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
}
}
}
+19
View File
@@ -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
}
}
}
+187 -74
View File
@@ -1,119 +1,232 @@
const VERBOSE = false;
const PLATFORM = Process.platform; // 'darwin' | 'windows'
const ARCH = Process.arch; // 'arm64' | 'x64' | 'x86_64' | ...
// ── Module Resolution ──
const getMainModule = (version) => {
if (PLATFORM === "darwin") {
return Process.findModuleByName("WeChatAppEx Framework");
}
// Windows: flue.dll for newer versions
if (version >= 13331) {
return Process.findModuleByName("flue.dll");
}
return Process.findModuleByName("WeChatAppEx.exe");
};
const patchCDPFilter = (base, config) => {
// xref: SendToClientFilter OR devtools_message_filter_applet_webview.cc
const offset = config.CDPFilterHookOffset;
// ── Scene Values ──
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), {
onEnter(args) {
send(
`[patch] CDP filter on enter, original value of input: ${args[0].readPointer()}`,
);
this.inputValue = args[0];
if (PLATFORM === "windows") {
this.inputValue = args[0];
}
},
onLeave(retval) {
const inputValue = this.inputValue.readPointer();
if (inputValue.isNull() || inputValue.add(8).isNull()) {
// there's a chance the value could be null
// return here to avoid crash
return;
let target;
if (PLATFORM === "darwin") {
// macOS: retval points directly to the struct
if (!retval || retval.isNull()) 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);
}
send(
`[patch] CDP filter on leave, patch input, now value: ${inputValue}; ` +
`*(input + 8) = ${inputValue.add(8).readU32()}`,
);
if (inputValue.add(8).readU32() == 6) {
inputValue.add(8).writeU32(0x0);
VERBOSE && console.log(`[patch] CDP filter v8[2]: ${target.readU32()}`);
if (target.readU32() === 6) {
target.writeU32(0x0);
}
},
});
};
const hookOnLoadScene = (a1, sceneOffsets) => {
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()}`);
// ── Resource Cache Policy Patch (darwin only) ──
// 1000: from issue #83 <-- will crash the process
// 1007: from issue #80
// 1008: from issue #53
// 1027: from issue #78
// 1035: from issue #78
// 1053: from issue #25
// 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 patchResourceCachePolicy = (base, offset) => {
// xref: WAPCAdapterAppIndex.js
Interceptor.attach(base.add(offset), {
onLeave(retval) {
VERBOSE && console.log(`[patch] cache policy retval: ${retval.toInt32()} -> 0`);
retval.replace(0x0);
},
});
};
const patchOnLoadStart = (base, config) => {
// xref: AppletIndexContainer::OnLoadStart
Interceptor.attach(base.add(config.LoadStartHookOffset), {
// ── OnLoadStart: Darwin ──
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) {
send(
`[inteceptor] AppletIndexContainer::OnLoadStart onEnter, ` +
`indexContainer.this: ${this.context.rcx}`,
);
// write dl to 0x1
try {
const v4 = args[0].add(8).readPointer();
if (!v4 || v4.isNull()) return;
const q1 = v4.add(structOffset).readPointer();
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) {
this.context.rdx = (this.context.rdx & ~0xff) | 0x1;
}
// handle onLoad scene
hookOnLoadScene(this.context.rcx, config.SceneOffsets);
},
onLeave(retval) {
// do nothing
// Scene hijack via SceneOffsets pointer chain
try {
const offsets = config.SceneOffsets;
const ptr1 = this.context.rcx.add(56).readPointer().add(offsets[0]).readPointer();
const scenePtr = ptr1.add(8).readPointer().add(offsets[1]).readPointer().add(16).readPointer().add(488);
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 rawConfig = `@@CONFIG@@`;
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 {
Version: 18955,
LoadStartHookOffset: "0x25B52C0",
CDPFilterHookOffset: "0x30248B0",
SceneOffsets: [1408, 1344],
SceneOffsets: [1408, 1344, 488],
};
}
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 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);
patchOnLoadStart(mainModule.base, config);
patchCDPFilter(mainModule.base, config);
if (!mainModule) {
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();
+461 -160
View File
File diff suppressed because it is too large Load Diff
+9 -2
View File
@@ -1,8 +1,15 @@
{
"theme": "dark",
"debug_port": "9421",
"cdp_port": "62000",
"debug_main": 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
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

+16
View File
@@ -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
+1
View File
@@ -2,3 +2,4 @@ frida>=17.0.0
websockets>=12.0
protobuf>=4.0.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
View File
@@ -4,7 +4,9 @@ DebugEngine - wraps debug_server, proxy_server, frida_server into a reusable cla
import asyncio
import json
import random
import platform
import re
import subprocess
import sys
from collections import Counter
from pathlib import Path
@@ -434,66 +436,95 @@ class DebugEngine:
# ── Frida ──
async def _start_frida(self):
logger = self.logger
# ── Frida: platform helpers ──
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()
processes = device.enumerate_processes(scope="metadata")
wmpf_processes = [p for p in processes if p.name == "WeChatAppEx.exe"]
if not wmpf_processes:
wmpf_procs = [p for p in processes if p.name == "WeChatAppEx.exe"]
if not wmpf_procs:
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
wmpf_ppids = []
for p in wmpf_processes:
ppid = p.parameters.get("ppid", 0)
wmpf_ppids.append(ppid if ppid else 0)
ppids = [p.parameters.get("ppid", 0) or 0 for p in wmpf_procs]
main_pid = Counter(ppids).most_common(1)[0][0]
if main_pid == 0:
raise RuntimeError("[frida] WeChatAppEx.exe main process not found")
if not wmpf_ppids:
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
main_proc = next((p for p in processes if p.pid == main_pid), None)
if main_proc is None:
raise RuntimeError("[frida] could not locate main WMPF process")
pid_counts = Counter(wmpf_ppids)
wmpf_pid = pid_counts.most_common(1)[0][0]
proc_path = main_proc.parameters.get("path", "")
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:
raise RuntimeError("[frida] WeChatAppEx.exe process not found")
return [main_pid], version
wmpf_process = None
for p in processes:
if p.pid == wmpf_pid:
wmpf_process = p
break
def _find_wmpf_pids_darwin(self):
"""macOS: find WeChatAppEx PIDs via pgrep, version via Info.plist."""
try:
out = subprocess.check_output(
["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:
raise RuntimeError("[frida] Could not find main WMPF process")
try:
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", "")
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")
return pids, 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):
# PyInstaller onefile: resources in _MEIPASS; onedir: next to exe
project_root = Path(getattr(sys, '_MEIPASS', Path(sys.executable).parent)).resolve()
# Find PIDs and version
if is_mac:
pids, wmpf_version = self._find_wmpf_pids_darwin()
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"
if not hook_path.exists():
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():
raise RuntimeError(f"[frida] version config not found: {wmpf_version}")
config_content = config_path.read_text(encoding="utf-8")
config_content = json.dumps(json.loads(config_content))
raise RuntimeError(f"[frida] version config not found: {platform_dir}/{wmpf_version}")
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)
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):
if message.get("type") == "error":
@@ -501,10 +532,22 @@ class DebugEngine:
return
logger.frida_debug("[frida client]", message.get("payload", ""))
script.on("message", on_message)
script.load()
for pid in pids:
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")
return session, script
+1 -1
View File
@@ -1,4 +1,4 @@
"""
r"""
extractor.py — 敏感信息提取引擎
直接使用 heartk_fast.py 的完整正则规则,保证提取结果一致
支持自定义正则规则,自定义类别会出现在导出报告中
Binary file not shown.
Binary file not shown.
+28 -9
View File
@@ -210,14 +210,33 @@ def find_wxapkg_files(packages_dir: str) -> List[dict]:
def get_default_packages_dir() -> Optional[str]:
"""获取默认的微信小程序包路径(Windows)"""
if os.name != "nt":
return None
"""获取默认的微信小程序包路径(Windows / macOS)"""
import sys
user_home = os.path.expanduser("~")
pkg_dir = os.path.join(
user_home, "AppData", "Roaming", "Tencent",
"xwechat", "radium", "Applet", "packages"
)
if os.path.isdir(pkg_dir):
return pkg_dir
if sys.platform == "darwin":
# macOS: ~/Library/Containers/com.tencent.xinWeChat/Data/Documents/app_data/radium/users/{wxid}/applet/packages
users_dir = os.path.join(
user_home, "Library", "Containers", "com.tencent.xinWeChat",
"Data", "Documents", "app_data", "radium", "users"
)
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
-87
View File
@@ -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);
})();
Generated
+235
View File
@@ -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" },
]
+101 -30
View File
@@ -1,48 +1,119 @@
@echo off
setlocal enabledelayedexpansion
title Launcher
chcp 437 >nul
title First - Launcher
cd /d "%~dp0"
:: Skip dependency check if already installed before
if exist ".deps_installed" goto :launch
set "CHOICE_FILE=.launch_choice"
:: 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 [WARNING] requirements.txt not found!
echo [WARNING] uv not found on this system.
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.
if /i "!choice!"=="Y" goto :launch
echo Cancelled.
timeout /t 2 >nul
echo [ERROR] uv sync failed. Check network or pyproject.toml.
pause
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
)
:: requirements.txt found, ask to install
echo.
echo [OK] requirements.txt found.
echo.
set /p "install= Install dependencies? [Y/N]: "
echo.
if /i "!install!"=="Y" (
echo Installing via Tsinghua mirror, please wait...
echo Checking dependencies...
python -c "import frida, websockets, google.protobuf, PySide6, Crypto" >nul 2>nul
if errorlevel 1 (
echo Some dependencies are missing.
echo.
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
if errorlevel 1 (
echo.
echo [ERROR] Installation failed! Check your network or pip config.
set /p INSTALLDEPS=" Install dependencies now? (pip install -r requirements.txt) [Y/N]: "
if /i "!INSTALLDEPS!"=="Y" (
echo Installing dependencies...
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
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
:launch
:RUN_SYSTEM
echo system>"%CHOICE_FILE%"
start "" pythonw gui.py
exit /b 0
Executable
+137
View File
@@ -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