| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- """Retry TCP CS 2001 login with CORRECT params, exactly per decrypted LoginProxy.lua.
- Key corrections vs the failed attempt:
- 1. param3 = server port (8021), NOT the connect port (12000)
- 2. param1 = random(100000000, 2100000000) & 0xFFFF00FF (NetStamp fallback)
- 3. connect to proxyport (12000) — that part was already right
- 4. body = account/Encode6BitBuf(password)/Encode6BitBuf(channelID)/otpType/otpCode
- From LoginProxy.lua:
- sendStr = string.format("%s/%s/%s/%s/%s", account, pwdSession, encodechannelID, otpType, otpCode)
- recog = 900000
- param2 = mainServerId or serverId
- param3 = serverPort (NOT proxyport!)
- """
- import asyncio
- import base64
- import json
- import os
- import random
- import sys
- from pathlib import Path
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir, "src"))
- from cq2_sdk.env_loader import load_env
- load_env()
- from cq2_sdk.transport.framing import encode_frame, decode_frame
- from cq2_sdk.utils.encoding import encode6bit
- if hasattr(sys.stdout, "reconfigure"):
- sys.stdout.reconfigure(encoding="utf-8", errors="replace")
- GATEWAY = "gfgame.dhsf.xqhuyu.com"
- PROXY_PORT = 12000 # connect here
- SERVER_PORT = 8021 # param3 = this
- SERVER_ID = 14414738 # user's server (霸业12服)
- CHANNEL = "110585" # 玖扬复古176 channel
- def get_creds() -> tuple[str, str]:
- text = Path(r"D:\ProgramFiles\996box\GameBoxDownload\1\env.json").read_bytes().decode("utf-8", errors="replace")
- idx = text.find("eyJ")
- b64 = text[idx:].rstrip()
- padded = b64 + "=" * (-len(b64) % 4)
- obj, _ = json.JSONDecoder().raw_decode(base64.urlsafe_b64decode(padded).decode("utf-8", errors="replace"))
- return str(obj.get("uid", "")), str(obj.get("token", ""))
- def stamp_param1() -> int:
- """NetStamp fallback: bit._and(math.random(100000000,2100000000), 0xFFFF00FF)."""
- r = random.randint(100000000, 2100000000)
- return r & 0xFFFF00FF
- async def attempt(uid: str, token: str, sid: int, server_port: int, use_otp: str) -> None:
- print(f"--- attempt sid={sid} server_port={server_port} otp={use_otp!r} ---")
- # body per Lua: account / Encode6BitBuf(password) / Encode6BitBuf(channelID) / otpType / otpCode
- pwd_enc = encode6bit(token.encode()).decode("ascii")
- ch_enc = encode6bit(CHANNEL.encode()).decode("ascii")
- send_str = f"{uid}/{pwd_enc}/{ch_enc}/{use_otp}/0"
- param1 = stamp_param1()
- frame = encode_frame(2001, 900000, param1, sid, server_port, send_str.encode())
- print(f"frame {len(frame)}B: msg=2001 recog=900000 p1={param1} p2={sid} p3={server_port}")
- print(f"body ({len(send_str)}): {uid}/{pwd_enc[:24]}.../{ch_enc[:12]}.../{use_otp}/0")
- reader, writer = await asyncio.wait_for(asyncio.open_connection(GATEWAY, PROXY_PORT), timeout=6)
- try:
- writer.write(frame)
- await writer.drain()
- data = await asyncio.wait_for(reader.read(4096), timeout=8)
- if not data:
- print("RESULT: server closed connection (0 bytes)")
- return
- print(f"RESULT: got {len(data)} bytes")
- print(f" hex[:80]: {data[:80].hex()}")
- try:
- hdr, body = decode_frame(data)
- print(f" *** PARSED msg_id={hdr.msg_id} recog={hdr.recog} p1={hdr.param1} p2={hdr.param2} p3={hdr.param3}")
- print(f" body: {body[:200]!r}")
- if hdr.msg_id == 529:
- print(" *** *** SC 529 LOGIN KEY — LOGIN WORKS! *** ***")
- except Exception as e:
- print(f" (not a plaintext 24B frame: {e})")
- finally:
- writer.close()
- try:
- await writer.wait_closed()
- except Exception:
- pass
- async def main() -> None:
- uid, token = get_creds()
- print(f"uid={uid} token_len={len(token)}")
- print(f"gateway={GATEWAY}:{PROXY_PORT} sid={SERVER_ID} server_port={SERVER_PORT}")
- print()
- # otpType variants: "0" (none), "1"
- for otp in ("0", "1"):
- await attempt(uid, token, SERVER_ID, SERVER_PORT, otp)
- print()
- await asyncio.sleep(1)
- asyncio.run(main())
|