13 Commits
Author SHA1 Message Date
牟不懂哎 27f8bd58a1 Update gui.py 2026-04-09 09:13:45 +08:00
牟不懂哎 b995a8da72 Update gui.py 2026-04-09 09:04:00 +08:00
牟不懂哎 88b44692fb v1.0.2 2026-04-08 21:36:37 +08:00
牟不懂哎 efc9c4fcd3 Delete scan_reports directory 2026-04-08 13:27:15 +08:00
黑桃A d438911cc0 更新 README.md 2026-04-06 07:47:47 +08:00
0xsdeo d35c3df491 Update README.md 2026-04-05 16:18:04 +08:00
牟不懂哎 4c4f62c0aa Update README.md 2026-04-05 00:22:07 +08:00
牟不懂哎 8f1a891e82 Update README.md 2026-04-04 22:53:27 +08:00
牟不懂哎 9049c47d01 Update README.md 2026-04-03 23:22:12 +08:00
0xsdeo abc92a61c5 更新 README.md 2026-04-03 18:03:18 +08:00
牟不懂哎 bfae468f24 Update README.md 2026-04-03 17:40:41 +08:00
牟不懂哎 691ba674ba Update README.md 2026-04-03 17:39:46 +08:00
牟不懂哎 fe972acab0 Update README.md 2026-04-03 17:39:26 +08:00
38 changed files with 470 additions and 18044 deletions
+29 -5
View File
@@ -2,18 +2,22 @@
> 微信小程序调试工具 —— 基于 Frida + CDP 代理,支持 GUI 与 CLI 双模式 > 微信小程序调试工具 —— 基于 Frida + CDP 代理,支持 GUI 与 CLI 双模式
--- ---
改项目仅支持windows,macos用户使用dp虚拟机即可 本项目仅支持windows,macos用户使用dp虚拟机即可
## 截图预览 ## 截图预览
### 主界面 / Control Panel ### 主界面 / Control Panel
![QQ20260402-192426](https://s1.galgame.fun/imgb/u0/20260402_69ce51f6c6f60.png)
![zhuyem](https://s1.galgame.fun/imgb/u0/20260408_69d655f49ca7e.png)
### 路由导航 ### 路由导航
![微信图片_2026-04-02_192531_552](https://s1.galgame.fun/imgb/u0/20260402_69ce523e8b90d.png) ![luyou](https://s1.galgame.fun/imgb/u0/20260408_69d6560ca1a39.png)
### 云函数分析 ### 云函数分析
![QQ20260402-192623](https://s1.galgame.fun/imgb/u0/20260402_69ce527ca5480.png) ![QQ20260402-192623](https://s1.galgame.fun/imgb/u0/20260402_69ce527ca5480.png)
### 调试开关(JSRPC 与调用 wx.cloud)
![调试](https://s1.galgame.fun/imgb/u0/20260408_69d6564195009.png)
### 安全扫描 ### 安全扫描
待优化 待优化
@@ -50,6 +54,12 @@ pip install -r requirements.txt
--- ---
## 微信版本要求
- WMPF版本区间:19201-11581
- 推荐微信版本为4.1.0.30
- 下载地址[weixin/4.1.0.30](https://github.com/vs-olitus/wx-version/releases/tag/4.1.0.30)
## 使用方法 ## 使用方法
### GUI 模式(推荐) ### GUI 模式(推荐)
@@ -57,8 +67,12 @@ pip install -r requirements.txt
```bash ```bash
python gui.py python gui.py
``` ```
双击启动.bat
启动后在主界面点击 **启动调试** 即可开始调试。
启动后在主界面点击 **Start** 即可开始调试。 ### 小程序页面操作
点击启动调试前请勿打开小程序, **启动调试**打开后再次启动**小程序**即可。
### CLI 模式 ### CLI 模式
@@ -72,7 +86,6 @@ python main.py --debug-port 9421 --cdp-port 62000
# 开启详细日志 # 开启详细日志
python main.py --debug-main --debug-frida python main.py --debug-main --debug-frida
``` ```
### 连接 Chrome DevTools ### 连接 Chrome DevTools
启动后,在 Chrome 地址栏输入: 启动后,在 Chrome 地址栏输入:
@@ -112,6 +125,13 @@ pyinstaller WMPFDebugger.spec
--- ---
## 常见问题解决办法
1. Frida 已显示连接,但小程序端显示未连接
若操作顺序无误,建议先彻底卸载微信并重启电脑(如有重要聊天记录请提前备份)。
删除路径C:\Users\用户名\AppData\Roaming\Tencent\xwechat\XPlugin\Plugins\RadiumWMPF下所有以数字命名的文件夹,再次重启电脑后,安装微信 4.1.0.30 版本。安装完成后检查上述路径,确认文件夹编号为 16389。
## 参考项目 ## 参考项目
本项目参考并学习了以下优秀工具的实现思路: 本项目参考并学习了以下优秀工具的实现思路:
@@ -119,6 +139,7 @@ pyinstaller WMPFDebugger.spec
- [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)
--- ---
## 致谢 ## 致谢
@@ -126,6 +147,9 @@ pyinstaller WMPFDebugger.spec
感谢 **0xsdeo** 师傅的大力支持与思路提供。 感谢 **0xsdeo** 师傅的大力支持与思路提供。
--- ---
## 交流群
![微信图片_20260408212151_1256_3](https://s1.galgame.fun/imgb/u0/20260408_69d6567d777a9.jpg)
## 免责声明 ## 免责声明
-52
View File
@@ -1,52 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['gui.py'],
pathex=[],
binaries=[],
datas=[
('src/nav_inject.js', 'src'),
('src/cloud_audit_inject.js', 'src'),
('frida/hook.js', 'frida'),
('frida/config', 'frida/config'),
('icon.ico', '.'),
],
hiddenimports=[
'frida',
'websockets',
'google.protobuf',
'PySide6.QtCore',
'PySide6.QtGui',
'PySide6.QtWidgets',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='First',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['icon.ico'],
)
+430 -663
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -4,7 +4,5 @@
"cdp_port": "62000", "cdp_port": "62000",
"debug_main": false, "debug_main": false,
"debug_frida": false, "debug_frida": false,
"selected_preload_scripts": [ "selected_preload_scripts": []
"bypass_debugger.js"
]
} }
-299
View File
@@ -1,299 +0,0 @@
syntax = "proto2";
package mmbizwxadevremote;
message WARemoteDebug_DataFormat {
optional uint32 cmd = 1;
optional string uuid = 2;
optional bytes data = 3;
}
message WARemoteDebug_BaseReq {
optional uint32 clientVersion = 1;
}
message WARemoteDebug_BaseResp {
optional int32 errcode = 1;
optional string errmsg = 2;
}
message WARemoteDebug_CommReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
}
message WARemoteDebug_CommResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_DebugMessage {
optional uint32 seq = 1;
optional uint32 after = 2;
optional string category = 3;
optional bytes data = 4;
optional uint32 compressAlgo = 5;
optional uint32 originalSize = 6;
}
message WARemoteDebug_SendDebugMessageReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
repeated WARemoteDebug_DebugMessage debugMessageList = 2;
optional uint32 recvAck = 3;
}
message WARemoteDebug_SendDebugMessageResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
optional uint32 sendAck = 2;
}
message WARemoteDebug_NewSendDebugMessageReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
repeated WARemoteDebug_DebugMessage debugMessageList = 2;
optional uint32 recvAck = 3;
}
message WARemoteDebug_NewSendDebugMessageResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
optional uint32 minAck = 2;
optional uint32 maxAck = 3;
}
message WARemoteDebug_MessageNotify {
repeated WARemoteDebug_DebugMessage debugMessageList = 1;
}
message WARemoteDebug_MessageNotifyResp {
optional uint32 recvAck = 1;
}
message WARemoteDebug_EventNotify {
}
message WARemoteDebug_EventNotifyResp {
}
message WARemoteDebug_WxHeartBeatReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional uint32 recvAck = 2;
}
message WARemoteDebug_WxHeartBeatResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_DevHeartBeatReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional uint32 recvAck = 2;
}
message WARemoteDebug_DevHeartBeatResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_RoomInfo {
optional bool joinRoom = 1;
optional string roomId = 2;
optional string originalMd5 = 3;
optional uint32 roomStatus = 4;
optional uint32 wxConnStatus = 5;
optional uint32 devConnStatus = 6;
}
message WARemoteDebug_WxLoginReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional string loginTicket = 2;
}
message WARemoteDebug_WxLoginResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
optional WARemoteDebug_RoomInfo roomInfo = 2;
}
message WARemoteDebug_DevLoginReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional string newticket = 2;
optional uint32 autodev = 3;
}
message WARemoteDebug_DevLoginResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
optional WARemoteDebug_RoomInfo roomInfo = 2;
}
message WARemoteDebug_WxJoinRoomReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional string username = 2;
optional string roomId = 3;
optional string wxpkgInfo = 4;
}
message WARemoteDebug_WxJoinRoomResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_DevJoinRoomReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional string appid = 2;
optional string roomId = 3;
optional string wxpkgInfo = 4;
}
message WARemoteDebug_DevJoinRoomResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_WxQuitRoomReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
}
message WARemoteDebug_WxQuitRoomResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_DevQuitRoomReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
}
message WARemoteDebug_DevQuitRoomResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
}
message WARemoteDebug_WxSyncMessageReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional uint32 minSeq = 2;
optional uint32 maxSeq = 3;
}
message WARemoteDebug_WxSyncMessageResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
repeated WARemoteDebug_DebugMessage debugMessageList = 2;
optional uint32 sendAck = 3;
}
message WARemoteDebug_DevSyncMessageReq {
optional WARemoteDebug_BaseReq baseRequest = 1;
optional uint32 minSeq = 2;
optional uint32 maxSeq = 3;
}
message WARemoteDebug_DevSyncMessageResp {
optional WARemoteDebug_BaseResp baseResponse = 1;
repeated WARemoteDebug_DebugMessage debugMessageList = 2;
optional uint32 sendAck = 3;
}
message WARemoteDebug_MethodWithArgs {
optional string methodName = 1;
repeated string methodArgList = 2;
}
message WARemoteDebug_RegisterInterface {
optional string objName = 1;
repeated WARemoteDebug_MethodWithArgs objMethodList = 2;
}
message WARemoteDebug_DeviceInfo {
optional string deviceName = 1;
optional string deviceModel = 2;
optional string systemVersion = 3;
optional string wechatVersion = 4;
optional uint32 publibVersion = 5;
optional float screenWidth = 6;
optional float pixelRatio = 7;
optional string userAgent = 8;
}
message WARemoteDebug_SetupContext {
optional WARemoteDebug_RegisterInterface registerInterface = 1;
optional WARemoteDebug_DeviceInfo deviceInfo = 2;
optional string configureJs = 3;
optional string publicJsMd5 = 4;
optional string threeJsMd5 = 5;
optional uint32 supportCompressAlgo = 6;
}
message WARemoteDebug_CallInterface {
optional string objName = 1;
optional string methodName = 2;
repeated string methodArgList = 3;
optional uint32 callId = 4;
}
message WARemoteDebug_CallInterfaceResult {
optional string ret = 1;
optional uint32 callId = 2;
optional string debugInfo = 3;
}
message WARemoteDebug_EvaluateJavascript {
optional string script = 1;
optional uint32 evaluateId = 2;
optional string debugInfo = 3;
}
message WARemoteDebug_EvaluateJavascriptResult {
optional string ret = 1;
optional uint32 evaluateId = 2;
}
message WARemoteDebug_Breakpoint {
optional bool isHit = 1;
}
message WARemoteDebug_Ping {
optional uint64 pingId = 1;
optional string payload = 2;
}
message WARemoteDebug_Pong {
optional uint64 pingId = 1;
optional uint32 networkType = 2;
optional string payload = 3;
}
message WARemoteDebug_DomOp {
optional string params = 1;
optional uint32 webviewId = 2;
}
message WARemoteDebug_DomEvent {
optional string params = 1;
optional uint32 webviewId = 2;
}
message WARemoteDebug_NetworkDebugAPI {
optional string apiName = 1;
optional string taskId = 2;
optional string requestHeaders = 3;
optional uint64 timestamp = 4;
}
message WARemoteDebug_ChromeDevtools {
optional uint64 opId = 1;
optional string payload = 2;
optional string jscontextId = 3;
}
message WARemoteDebug_ChromeDevtoolsResult {
optional uint64 opId = 1;
optional string payload = 2;
optional string jscontextId = 3;
}
message WARemoteDebug_AddJsContext {
optional string jscontextId = 1;
optional string jscontextName = 2;
}
message WARemoteDebug_RemoveJsContext {
optional string jscontextId = 1;
}
message WARemoteDebug_ConnectJsContext {
optional string jscontextId = 1;
}
message WARemoteDebug_CustomMessage {
optional string method = 1;
optional string payload = 2;
optional bytes raw = 3;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
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.
+6 -1
View File
@@ -340,7 +340,7 @@ class DebugEngine:
logger.info(f"[userscript] immediate inject (Runtime.evaluate): {script.name}") logger.info(f"[userscript] immediate inject (Runtime.evaluate): {script.name}")
engine.message_counter = seq engine.message_counter = seq
except Exception as e: except Exception as e:
logger.error(f"[userscript] immediate inject error: {e}") logger.warn(f"[userscript] immediate inject warning: {e}")
except websockets.exceptions.ConnectionClosed: except websockets.exceptions.ConnectionClosed:
pass pass
except Exception as e: except Exception as e:
@@ -349,6 +349,11 @@ class DebugEngine:
engine.miniapp_clients.discard(websocket) engine.miniapp_clients.discard(websocket)
if not engine.miniapp_clients: if not engine.miniapp_clients:
engine._notify_status("miniapp", False) engine._notify_status("miniapp", False)
# 清理所有挂起的 CDP 响应,防止 future 泄漏
for fid, fut in list(engine._pending_responses.items()):
if not fut.done():
fut.set_exception(RuntimeError("miniapp disconnected"))
engine._pending_responses.clear()
logger.info("[miniapp] miniapp client disconnected") logger.info("[miniapp] miniapp client disconnected")
server = await websockets.server.serve( server = await websockets.server.serve(
+4 -1
View File
@@ -32,7 +32,10 @@ class MiniProgramNavigator:
"tabBar:window.nav?window.nav.tabBarPages:[]," "tabBar:window.nav?window.nav.tabBarPages:[],"
"appid:window.nav&&window.nav.config?(window.nav.config.appid||''):''," "appid:window.nav&&window.nav.config?(window.nav.config.appid||''):'',"
"entry:window.nav&&window.nav.config?(window.nav.config.entryPagePath||''):''," "entry:window.nav&&window.nav.config?(window.nav.config.entryPagePath||''):'',"
"name:(function(){try{var a=window.__wxConfig||window.wx&&window.wx.__wxConfig||{};" "name:(function(){try{"
"var f=window.nav&&window.nav.wxFrame;"
"var a=(f&&f.__wxConfig)||window.__wxConfig||"
"(window.wx&&window.wx.__wxConfig)||{};"
"var b=a.accountInfo&&a.accountInfo.appAccount;" "var b=a.accountInfo&&a.accountInfo.appAccount;"
"return b&&b.nickname||a.appname||''}catch(e){return ''}})()" "return b&&b.nickname||a.appname||''}catch(e){return ''}})()"
"})", "})",
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.