移除二维码信封历史数据依赖

This commit is contained in:
yml2213
2026-08-31 17:43:55 +08:00
parent 05b1325a04
commit d391e2ce3e
6 changed files with 546 additions and 937 deletions
+98 -14
View File
@@ -1,6 +1,7 @@
"""wupData 信封构造与补丁工具。
解析与改写 WUP 信封中的 cert、uid、session 等字段。
生产二维码信封由 :meth:`Envelope.build_qr` 按当前账号状态编码;
:meth:`Envelope.load` 仅保留协议结构模板兼容测试和离线分析。
"""
from __future__ import annotations
@@ -10,7 +11,8 @@ import json
import struct
from pathlib import Path
from loguru import logger
from .taf_protocol import TafOutputStream
from .wup_protocol import WupRequest
INT8, INT16, INT32, INT64 = 0x00, 0x01, 0x02, 0x03
STRING1, STRING4 = 0x06, 0x07
@@ -119,24 +121,106 @@ class Envelope:
@classmethod
def load(cls, path: str | Path | None = None) -> Envelope:
"""加载信封模板,支持从文件加载或使用内嵌金样本。"""
"""加载显式模板,或使用内嵌协议结构模板。
不自动扫描 ``evidence/``,避免历史抓包成为隐式生产输入。
"""
if path:
p = Path(path)
if p.exists():
return cls._load_from_path(p)
# 尝试查找 evidence/cert_keycap.json
candidate = (
Path(__file__).resolve().parent.parent.parent
/ "evidence"
/ "cert_keycap.json"
)
if candidate.exists():
try:
return cls._load_from_path(candidate)
except Exception as exc: # noqa: BLE001
logger.debug(f"加载证书信封候选文件失败: {candidate}: {exc}")
return cls(base64.b64decode(PROTOCOL_QURL_TEMPLATE_B64))
@classmethod
def build_qr(
cls,
*,
uid: int,
cert_b64: str,
safedeviceid: str,
session: int,
trace_id: str,
device_info: dict[str, str],
) -> Envelope:
"""按当前账号状态编码二维码绑定信封。
生产二维码请求不应从抓包信封复制字段。这里仅复用已知的 TAF/WUP
字段布局;证书、ACTION、UID、会话和全部设备画像都由本次登录提供。
"""
if len(cert_b64) != 260:
raise ValueError(f"证书 base64 长度异常: {len(cert_b64)} != 260")
if len(safedeviceid) != 180:
raise ValueError(f"safedeviceid 长度异常: {len(safedeviceid)} != 180")
dev = {k: str(v) for k, v in (device_info or {}).items()}
meta = json.dumps(
{
"associationId": 184549392,
"funcName": "",
"group": 0,
"id": 184549392,
"session": int(session),
"step": 0,
"stillLogin": False,
"traceId": str(trace_id),
"type": 2,
"uid": 0,
"userContext": "",
},
ensure_ascii=False,
separators=(",", ":"),
)
body = TafOutputStream()
body.write_struct_begin(0)
body.write_struct_begin(0)
body.write_int8(0, 0)
body.write_string(1, "1.0")
body.write_string(2, meta)
body.write_string(3, "5008")
body.write_int8(4, 3)
body.write_string(5, safedeviceid)
body.write_string(6, "")
body.write_string(7, "")
body.write_string(8, "")
body.write_string(9, "")
body.write_struct_end()
body.write_struct_begin(1)
body.write_string(0, dev.get("hdid", ""))
body.write_string(1, dev.get("app_version", "13.4.22"))
body.write_string(2, dev.get("sdk_version", "1.0.80138"))
body.write_string(3, "")
body.write_string(4, dev.get("ip", "127.0.0.1"))
body.write_string(5, dev.get("vendor", "android"))
body.write_string(6, "")
body.write_struct_end()
body.write_struct_begin(2)
body.write_int8(0, 1)
body.write_string(1, dev.get("model", ""))
body.write_string(2, dev.get("fingerprint", ""))
body.write_string(3, dev.get("os", "android"))
body.write_string(4, dev.get("screen", ""))
body.write_string(6, dev.get("width", "1080"))
body.write_string(7, dev.get("height", "2120"))
body.write_string(8, dev.get("device_id", ""))
body.write_struct_end()
body.write_uint64(3, int(uid))
body.write_string(4, cert_b64)
body.write_string(5, "")
body.write_string(6, "")
body.write_struct_end()
req = TafOutputStream()
req.write_int32(0, int(session))
wup = WupRequest()
wup.iTimeout = 0
wup.setRequestId(int(session))
wup.setServant("huyaudbwebui")
wup.setFunc("default")
wup.newdata["_wup_data"] = body.get_bytes()
wup.newdata["wupudbrequest_v0"] = req.get_bytes()
return cls(wup.encode())
@classmethod
def _load_from_path(cls, p: Path) -> Envelope:
if p.suffix == ".json":