feat(huya): doLaunch live对拍定案 - 信封/键/路径被服务端接受, tReq值恒定拒绝

- App侧全细节确认: a09.getRequestKey=tReq / UniPacket(true)=v3 / 值=write(struct,0)
  / URL=/launch/doLaunch / getOtherParams追加 platform/version/channel/uid 键
  / 传输类型服务端动态下发(HTTP是否真渠道未定)
- live诊断: E(空值)->require field / F(缺键)->not found key / G(0x0c)->完全复现
  'read struct type mismatch tag0 type12' -> 服务端确实解析tReq值, 语义与本地djce不同
- 工具升级: --live 用5键 App同等 map; 悬而未决点=需App真实doLaunch帧(约束内路径全探)
  - logcat无klog / xlog+mmap2 mars压缩不解 / 冷启动走缓存不发网络launch / 禁pm clear
  - 可选项: 代理+CA被动抓包 / 模拟器新装 / 继续抠mars xlog
This commit is contained in:
yml2213
2026-08-28 19:13:36 +08:00
parent 44109aa408
commit d2adfb25ad
2 changed files with 58 additions and 5 deletions
+25 -5
View File
@@ -16,8 +16,13 @@
- --dump : 打印请求体结构/hex (不联网)
- --live [url] : 真实发送 (默认 https://wup.huya.com)
传输细节 (hyns/KiwiServant a09 栈) 未完全静态定案: 先按经典 UniPacket + wup.huya.com
平铺, live 测试确认服务端接受度后再校准; 字段/tag 均已按 dex 精确还原.
实测状态 (2026-08-29):
- 信封/路径/键均被服务端接受: servant/func 回声, UniAttribute 找到 tReq 键;
但 tReq 值被拒: "read 'struct' type mismatch, tag: 0, get type: 12" (恒定).
- 诊断: 值=0x0c 复现同错 (E:空值->require field; F:缺键->not found key) => 服务端在
解析值, 但首字段始终判为 ZERO. 疑点: a09 传输类型由服务端动态配置
(IFunctionTranspotModule.getTransportType("launch#doLaunch")), HTTP POST 路径
未必是 doLaunch 真渠道; wire 已逐字节对齐 App (见 docs §11.6), 待真机帧定案.
用法:
python tools/huya_launch_mint.py --self-test
@@ -97,10 +102,20 @@ def build_live_launch_wup(profile: dict, request_id: int | None = None) -> bytes
request_id = int.from_bytes(__import__("os").urandom(4), "big") & 0x7FFFFFFF
req_jce = encode_live_launch_req(profile)
# App 端 a09.getOtherParams() 还会追加 platform/version/channel/(yyuid/uid/imei) 键
entries = [("tReq", ("bytes", req_jce))]
for k in ("platform", "version", "channel", "yyuid", "uid", "imei"):
v = profile.get(k)
if v:
entries.append((k, ("string", v)))
sb = _Writer()
sb.map_begin(0, 1)
sb.string(0, "_wup_data")
sb.bytes(1, req_jce)
sb.map_begin(0, len(entries))
for k, (kind, val) in entries:
sb.string(0, k)
if kind == "bytes":
sb.bytes(1, val)
else:
sb.string(1, val)
s_buffer = sb.get()
w = _Writer()
@@ -272,6 +287,11 @@ DEFAULT_PROFILE = {
"net_type": "",
"token": "",
"cookie": "",
"platform": "android",
"version": "13.4.22",
"channel": "xxx",
"yyuid": "0",
"uid": "0",
}