docs(tng): 补充 Money Packet 领取台说明,并同步自动拉详情 Hook

说明 activityId、手动缓存模板后再自动拉历史详情的流程,以及 /mmp 双通道与去重行为。
This commit is contained in:
mars
2026-08-04 15:39:44 +08:00
parent 88a2b319f8
commit 1e2021d8fd
5 changed files with 719 additions and 47 deletions

View File

@@ -0,0 +1,120 @@
# TNG Money Packet 领取台说明
> 更新2026-08-04
> 相关代码:`TngMoneyPacketHook.java`、`debug-server/server.py`、`AppConfig.DEBUG_SERVER_URLS`
## 目标
抓取 TNG eWallet **Money Packet红包** 的领取排行:谁领了、领了多少,并在 PC 调试台按**单个红包**展示。
## 页面与地址
| 入口 | 地址 |
|------|------|
| 本机USB + `adb reverse` | http://127.0.0.1:8765/mmp |
| 局域网 / USB 共享网 | http://<电脑IP>:8765/mmp (当前常见:`http://10.151.104.25:8765/mmp` |
| 通用消息台 | http://127.0.0.1:8765/ |
手机推送会同时尝试:
- `http://127.0.0.1:8765`(需 `adb reverse tcp:8765 tcp:8765`
- `http://10.151.104.25:8765`USB 共享网段;若电脑 IP 变了,改 `AppConfig.DEBUG_SERVER_URLS`
启动调试台:
```powershell
powershell -ExecutionPolicy Bypass -File scripts/start-debug-server.ps1
```
## 红包唯一标识
正式字段是 **`activityId`**UUID例如
- `b8c37a58-bb2c-4aa2-83ef-f15466b9211e`
- `e5dcf293-4062-4df4-a692-e3bf194d9a37`
领取台左侧按 `activityId` 分条;详情页会显示完整 ID。
转发正文格式示例:
```text
[MMP统计] packet=<activityId> | sender=... | total=1.00 | via=rpc | src=moneyPacketDetail
昵称A -> 0.71
昵称B -> 0.29
```
金额在 App 内多为 Money 对象 `{"amount":"0.71","cent":"71",...}`Hook / 调试台会规范成数字再展示。
## 数据从哪来
| 来源 | Quake op / 方法 | 内容 |
|------|-----------------|------|
| 历史列表 | `moneyPacketHistoryList` / `ap.tngdwallet.moneyPacket.list.retrieve` | 仅摘要:`activityId`、总额、时间等,**无领取排行** |
| 红包详情 | `moneyPacketDetail` / `ap.tngdwallet.moneyPacket.retrieve` | 含 `activityPoolInfos`(领取人 + 金额) |
外部 mitm 因证书 pinning **解不开** TNG API 正文;必须用进程内 Xposed`TngMoneyPacketHook`)。
消费端详情领取列表字段主要是 **`activityPoolInfos`**`receiverName` + `amount`),不是商户版的 `receiverList`
## 推荐操作流程(自动拉详情)
历史页本身没有排行数据。自动拉取需要一次「带登录态的详情请求」作模板:
1. 打开 TNG → **Money Packet**
2. **先手动点开任意一条历史红包详情**(看到排行榜即可)
- 日志:`cached detail request template`(缓存 session / 请求模板)
3. **返回历史列表**,停留几秒
- 日志:`history hit → schedule auto detail`
- 随后:`auto-detail using template` / `auto-detail ok activityId=... claims=N`
4. 刷新领取台http://127.0.0.1:8765/mmp
若跳过第 2 步,自动请求常返回 `totalCount:0`(缺 `sessionId` 等),台上会没有领取人。
也可继续「只点详情」:每进一个详情就会捕获该 `activityId` 的排行。
## 去重与刷新行为
| 规则 | 说明 |
|------|------|
| 标识 | 以 `activityId` 区分红包 |
| 短时去重 | 同一 `activityId` + **相同领取名单**,约 **20 秒内**不重复推送(防双 Hook / 连点) |
| 可刷新 | 超过 20 秒再进详情,或领取名单变化,会再次推送 |
| 自动拉冷却 | 同一 `activityId` 自动拉详情成功后约 **60 秒**内不重复自动拉 |
| 调试台 | 同一 `activityId` 只保留最新完整快照做排行;双通道推送有短时内容去重 |
日志里若出现 `skip dup activityId=...`,表示短时去重生效,不是没抓到。
## 排障
```text
adb logcat | findstr TngMmp
```
常见日志:
| 日志 | 含义 |
|------|------|
| `TngMmp installed` | Hook 已加载 |
| `cached RPC task MoneyPacketRpcTask` | 已缓存 RPC 代理 |
| `cached detail request template` | 已缓存手动详情请求(自动拉可用) |
| `history hit → schedule auto detail` | 历史列表触发自动拉 |
| `auto-detail empty claims ... totalCount:0` | 请求缺登录态或模板未缓存 |
| `auto-detail ok activityId=... claims=N` | 自动拉成功 |
| `captured activityId=... claims=N` | 已转发到 notiMessage / 调试台 |
其它检查:
1. LSPosed 作用域包含 `my.com.tngdigital.ewallet`,模块为最新 APK
2. 强停后再开 TNG使新 Hook 生效
3. 调试台进程在跑USB 时执行过 `adb reverse`
4. notiMessage 监听列表勾选了 TNGHook 转发依赖主 App 接收广播)
5. 电脑 USB 共享 IP 变化后更新 `AppConfig.DEBUG_SERVER_URLS` 并重装主 App
## 相关文件
| 文件 | 作用 |
|------|------|
| `xposed-module/.../hook/TngMoneyPacketHook.java` | Quake RPC Hook、自动拉详情、金额/`activityId` 解析 |
| `debug-server/server.py` | `/mmp` 领取台、`/api/mmp` |
| `app/.../AppConfig.java` | `DEBUG_SERVER_URLS` 双地址 |
| `app/.../network/DebugForwarder.java` | 向多个调试地址推送 |
| `scripts/start-debug-server.ps1` | 启动调试台 + adb reverse |

View File

@@ -11,42 +11,25 @@
---
## Money Packet 领取统计 — 网络/明文获取能力
## Money Packet 领取统计
目标:群红包 Leaderboard 的 **昵称 + 已领金额**(字段预期 `receiverList` / `claimedAmount` 等)
**专用说明(操作 / 标识 / 自动拉详情 / 排障):** 见 [TNG_MoneyPacket领取台.md](TNG_MoneyPacket领取台.md)
### 路线对比
### 能力摘要
| 路线 | 状态 | 说明 |
|------|------|------|
| 外部 mitmCharles / mitmproxy | **不可行(当前)** | TNG API`mpaasgw.tngdigital.com.my`)有 **证书 pinning**,只能看到域名,解不开 HTTPS 正文。`reverse/dumps/mitm_mmp/` 里曾落盘的多为官网 HTML/新闻,**不是** 红包 API。 |
| 进程内 Xposed`TngMoneyPacketHook` | **代码已接,运行时未实证** | 在 TLS 之后读明文Hook `OkHttp ResponseBody.string` + `Gson.fromJson`,匹配 `receiverList` / `claimedAmount` / `Mmp*` 模型,经 `HookForwarder` 转发。`MainHook``install` |
| 纯日志/UI 自动化 | 兜底 | 无 API 时可读界面,不稳定,不作主路径。 |
| 外部 mitm | **不可行** | API 证书 pinning解不开正文 |
| Xposed `TngMoneyPacketHook` | **实证** | Hook Quake `moneyPacketDetail` / 历史列表触发自动拉详情;标识为 `activityId` |
| PC 领取台 | **已上线** | http://127.0.0.1:8765/mmp ,按单个红包展示排行 |
### 当前缺口
### 要点
1. **尚未在真机打开 Money Packet Leaderboard 做过一次捕获验证** → logcat 里暂无 `TngMmp captured …`
2. TNG 主业务多为 **mPaaS / Quake RPC**,若响应不走 `ResponseBody.string()` / 目标 Gson 类名不符,现有 Hook 会漏;需补 **RPC invoke 返回值 / 其它 JSON 入口**
3. Splash 强拉登录不影响「登录后进群点红包」时的抓包,但影响复测效率
### 建议验证步骤(下次动手)
1. 保持登录态,进群 → 打开红包详情 / Leaderboard。
2. 看 LSPosed`notiMessageHook/TngMmp installed``captured packet=… claims=N`
3. 若无:对同一次操作抓 logcat 里 URL / 类名,补 Hook 点Quake `RpcInvocationHandler` 等)。
4. 确认 notiMessage / debug-server 是否收到转发内容。
1. 历史列表只有摘要;领取排行来自详情 RPC`activityPoolInfos`
2. **自动拉详情**:先手动点开任意一条详情缓存请求模板(含 session再回历史页即可批量拉
3. 去重:同一 `activityId` + 相同领取名单约 20s 内不重复推
### eKYC「验证您的帐户」强制页2026-08-04
`HomeEkycVerifyActivity` 挡首页。测试期:`hookHomeEkycVerifySkip` — finish 该页 + 拦 Intent + `canBypassEkyc`/`enforceEkyc` stub。
**注意:** 服务端仍可能在部分功能(转账/红包)二次校验 eKYC首页跳过不等于全功能可用。
```text
packetId / title
receiverList[]:
- nickname / displayName
- claimedAmount或 amount
```
按昵称聚合 `claimedAmount` 即可做领取排行。