修正活动WSS AUTH帧对齐9.1抓包字节

This commit is contained in:
yml2213
2026-09-01 20:25:31 +08:00
parent 727c32a5f5
commit 9f3e3a74ce
2 changed files with 38 additions and 4 deletions
+18 -2
View File
@@ -568,12 +568,28 @@ class HuyaWssClient:
return body return body
async def send_auth(self, uid: int, cookie: str, sequence: int = SEQ_WSLAUNCH): async def send_auth(self, uid: int, cookie: str, sequence: int = SEQ_WSLAUNCH):
"""cmd 0x0a AUTH — 发送 TAF 认证结构(与 9.1 活动帧一致)。""" """cmd 0x0a AUTH — 对齐 9.1 抓包(828 活动帧)。
9.1 活动 AUTH 结构(逐字节核验):
tag3 ZERO ← 首字段(活动通道)
tag0 INT64 = uid
tag1 STRING1 = UA
tag2 STRING4 = cookie(含 huya_ua= 前缀)
tag3 STRING1 = guid32hex9.1 中为页面 Cookie 的 guid
tag4 INT8 = 1
tag5 STRING1 = "HUYA&ZH&2052"
tag6 STRING1 = ""
+= TAIL_BYTEStag2 ZERO/tag3 ""/tag4 ZERO/tag5 ZERO/tag6 ""
"""
os = TafOutputStream() os = TafOutputStream()
if self._activity_mode:
os.write_head(3, TafType.ZERO)
os.write_int64(0, int(uid or 0)) os.write_int64(0, int(uid or 0))
os.write_string(1, WSS_COOKIE_UA) os.write_string(1, WSS_COOKIE_UA)
os.write_string(2, HuyaWssClient._normalize_biz_cookie(cookie)) os.write_string(2, HuyaWssClient._normalize_biz_cookie(cookie))
os.write_int32(3, 0) guid_match = re.search(r"(?:^|;\s*)guid=([^;]+)", cookie or "")
guid = (guid_match.group(1).strip() if guid_match else "") or self._launch_guid
os.write_string(3, guid or "")
os.write_int8(4, 1) os.write_int8(4, 1)
os.write_string(5, "HUYA&ZH&2052") os.write_string(5, "HUYA&ZH&2052")
os.write_string(6, "") os.write_string(6, "")
+20 -2
View File
@@ -106,10 +106,21 @@ def test_wss_requires_web_device_cookie_fields():
def test_activity_auth_frame_matches_latest_capture_layout(): def test_activity_auth_frame_matches_latest_capture_layout():
"""对齐 9.1 活动 AUTH(828 连接)逐字段结构。
9.1: tag3 ZERO 首字段 -> tag0 uid -> tag1 UA -> tag2 cookie(STRING4)
-> tag3 STRING1 guid(32hex) -> tag4 INT8=1 -> tag5 "HUYA&ZH&2052"
-> tag6 "" -> TAIL_BYTES
"""
async def build_frame(): async def build_frame():
client = HuyaWssClient() client = HuyaWssClient()
client._activity_mode = True
client.ws = type("FakeWs", (), {"send": AsyncMock()})() client.ws = type("FakeWs", (), {"send": AsyncMock()})()
await client.send_auth(1199664135026, "udb_cred=" + "x" * 300, sequence=0x1D000109) await client.send_auth(
1199664135026,
"guid=" + "0a" * 16 + "; udb_cred=" + "x" * 300,
sequence=0x1D000109,
)
return client.ws.send.call_args.args[0] return client.ws.send.call_args.args[0]
message = WssMessage.decode(asyncio.run(build_frame())) message = WssMessage.decode(asyncio.run(build_frame()))
@@ -118,13 +129,20 @@ def test_activity_auth_frame_matches_latest_capture_layout():
assert message.body.endswith(TAIL_BYTES) assert message.body.endswith(TAIL_BYTES)
stream = TafInputStream(message.body[: -len(TAIL_BYTES)]) stream = TafInputStream(message.body[: -len(TAIL_BYTES)])
# 首字段:tag3 ZERO(9.1 活动帧的占位字段)
assert stream.read_head() == (3, TafType.ZERO)
assert stream.read_int64(0) == 1199664135026 assert stream.read_int64(0) == 1199664135026
assert stream.read_string(1) == "webh5&0.0.1&websocket&&diypc_52775" assert stream.read_string(1) == "webh5&0.0.1&websocket&&diypc_52775"
assert stream.read_head() == (2, TafType.STRING4) assert stream.read_head() == (2, TafType.STRING4)
cookie_len = int.from_bytes(stream.buf.read(4), "big") cookie_len = int.from_bytes(stream.buf.read(4), "big")
assert cookie_len > 255 assert cookie_len > 255
stream.buf.read(cookie_len) stream.buf.read(cookie_len)
assert stream.read_int32(3) == 0 # tag3 = STRING1 guid9.1 中为 Cookie 里的 32hex guid
guid = stream.read_string(3)
assert guid == "0a" * 16
assert stream.read_int8(4) == 1 assert stream.read_int8(4) == 1
assert stream.read_string(5) == "HUYA&ZH&2052" assert stream.read_string(5) == "HUYA&ZH&2052"
assert stream.read_string(6) == "" assert stream.read_string(6) == ""
# body 必须与 9.1 828 AUTH 同样以 TAIL_BYTES 收尾
assert message.body[-len(TAIL_BYTES):] == TAIL_BYTES