fix(tng): 修复区号页 HWUI 闪退并放行 Compose HW 绘制

拦截 HardwareRenderer.setName,校验/缓存 libandroid.so,避免软件绘制撞 hardware bitmap;附带 Money Packet hook 与 mitm 脚本。
This commit is contained in:
mars
2026-08-04 12:26:27 +08:00
parent 609635aba1
commit 5378a34f58
8 changed files with 1394 additions and 76 deletions

View File

@@ -0,0 +1,137 @@
#!/usr/bin/env python3
"""
mitmproxy 插件:自动保存 TNG Money Packet 含 receiverList 的 API 响应。
用法:
mitmdump -s debug-server/tng_mmp_mitm_addon.py -p 8888
mitmweb -s debug-server/tng_mmp_mitm_addon.py -p 8888
手机 WiFi 代理 -> PC_IP:8888安装 mitmproxy CA 后打开 TNG 红包 Leaderboard。
命中响应会打印到终端,并写入 reverse/dumps/mitm_mmp/
"""
from __future__ import annotations
import json
import os
import re
from datetime import datetime
from mitmproxy import ctx, http
OUTPUT_DIR = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"reverse",
"dumps",
"mitm_mmp",
)
MMP_HINTS = (
"receiverlist",
"claimedamount",
"mmpreceiver",
"moneypacket",
"merchantmoneypacket",
)
HOST_HINTS = (
"ebuckler.com",
"tngdigital.com",
"alipaydev.com",
)
def _ensure_dir() -> None:
os.makedirs(OUTPUT_DIR, exist_ok=True)
def _looks_like_mmp(body: str) -> bool:
lower = body.lower()
if any(h in lower for h in MMP_HINTS):
return True
return "mmp" in lower and "amount" in lower
def _extract_receiver_list(obj):
"""递归找 receiverList 并格式化为 [(nickname, amount), ...]"""
rows = []
def walk(node):
if isinstance(node, dict):
if "receiverList" in node and isinstance(node["receiverList"], list):
for item in node["receiverList"]:
if not isinstance(item, dict):
continue
name = (
item.get("nickName")
or item.get("displayName")
or item.get("userName")
or item.get("receiverName")
or item.get("name")
)
amount = (
item.get("claimedAmount")
or item.get("receiveAmount")
or item.get("amount")
)
if name and amount is not None:
rows.append((str(name), str(amount)))
for v in node.values():
walk(v)
elif isinstance(node, list):
for v in node:
walk(v)
walk(obj)
return rows
class TngMmpCapture:
def __init__(self) -> None:
_ensure_dir()
self.count = 0
ctx.log.info(f"TNG MMP capture -> {OUTPUT_DIR}")
def response(self, flow: http.HTTPFlow) -> None:
if flow.response is None or not flow.response.content:
return
host = (flow.request.host or "").lower()
if not any(h in host for h in HOST_HINTS):
return
try:
text = flow.response.get_text(strict=False)
except Exception:
return
if not text or not _looks_like_mmp(text):
return
self.count += 1
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_host = re.sub(r"[^\w.-]", "_", host)[:40]
path = os.path.join(OUTPUT_DIR, f"mmp_{ts}_{self.count}_{safe_host}.json")
summary_lines = [
f"[TNG-MMP #{self.count}] {flow.request.method} {flow.request.url}",
]
try:
data = json.loads(text)
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
rows = _extract_receiver_list(data)
if rows:
summary_lines.append(f" receiverList ({len(rows)} 条):")
for name, amount in rows:
summary_lines.append(f" {name} -> {amount}")
else:
summary_lines.append(" (JSON 已保存,未解析到 receiverList)")
except json.JSONDecodeError:
with open(path, "w", encoding="utf-8") as f:
f.write(text)
summary_lines.append(" (非 JSON已保存原文)")
summary_lines.append(f" saved: {path}")
ctx.log.info("\n".join(summary_lines))
addons = [TngMmpCapture()]