login_corrected.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """Retry TCP CS 2001 login with CORRECT params, exactly per decrypted LoginProxy.lua.
  2. Key corrections vs the failed attempt:
  3. 1. param3 = server port (8021), NOT the connect port (12000)
  4. 2. param1 = random(100000000, 2100000000) & 0xFFFF00FF (NetStamp fallback)
  5. 3. connect to proxyport (12000) — that part was already right
  6. 4. body = account/Encode6BitBuf(password)/Encode6BitBuf(channelID)/otpType/otpCode
  7. From LoginProxy.lua:
  8. sendStr = string.format("%s/%s/%s/%s/%s", account, pwdSession, encodechannelID, otpType, otpCode)
  9. recog = 900000
  10. param2 = mainServerId or serverId
  11. param3 = serverPort (NOT proxyport!)
  12. """
  13. import asyncio
  14. import base64
  15. import json
  16. import os
  17. import random
  18. import sys
  19. from pathlib import Path
  20. sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir, "src"))
  21. from cq2_sdk.env_loader import load_env
  22. load_env()
  23. from cq2_sdk.transport.framing import encode_frame, decode_frame
  24. from cq2_sdk.utils.encoding import encode6bit
  25. if hasattr(sys.stdout, "reconfigure"):
  26. sys.stdout.reconfigure(encoding="utf-8", errors="replace")
  27. GATEWAY = "gfgame.dhsf.xqhuyu.com"
  28. PROXY_PORT = 12000 # connect here
  29. SERVER_PORT = 8021 # param3 = this
  30. SERVER_ID = 14414738 # user's server (霸业12服)
  31. CHANNEL = "110585" # 玖扬复古176 channel
  32. def get_creds() -> tuple[str, str]:
  33. text = Path(r"D:\ProgramFiles\996box\GameBoxDownload\1\env.json").read_bytes().decode("utf-8", errors="replace")
  34. idx = text.find("eyJ")
  35. b64 = text[idx:].rstrip()
  36. padded = b64 + "=" * (-len(b64) % 4)
  37. obj, _ = json.JSONDecoder().raw_decode(base64.urlsafe_b64decode(padded).decode("utf-8", errors="replace"))
  38. return str(obj.get("uid", "")), str(obj.get("token", ""))
  39. def stamp_param1() -> int:
  40. """NetStamp fallback: bit._and(math.random(100000000,2100000000), 0xFFFF00FF)."""
  41. r = random.randint(100000000, 2100000000)
  42. return r & 0xFFFF00FF
  43. async def attempt(uid: str, token: str, sid: int, server_port: int, use_otp: str) -> None:
  44. print(f"--- attempt sid={sid} server_port={server_port} otp={use_otp!r} ---")
  45. # body per Lua: account / Encode6BitBuf(password) / Encode6BitBuf(channelID) / otpType / otpCode
  46. pwd_enc = encode6bit(token.encode()).decode("ascii")
  47. ch_enc = encode6bit(CHANNEL.encode()).decode("ascii")
  48. send_str = f"{uid}/{pwd_enc}/{ch_enc}/{use_otp}/0"
  49. param1 = stamp_param1()
  50. frame = encode_frame(2001, 900000, param1, sid, server_port, send_str.encode())
  51. print(f"frame {len(frame)}B: msg=2001 recog=900000 p1={param1} p2={sid} p3={server_port}")
  52. print(f"body ({len(send_str)}): {uid}/{pwd_enc[:24]}.../{ch_enc[:12]}.../{use_otp}/0")
  53. reader, writer = await asyncio.wait_for(asyncio.open_connection(GATEWAY, PROXY_PORT), timeout=6)
  54. try:
  55. writer.write(frame)
  56. await writer.drain()
  57. data = await asyncio.wait_for(reader.read(4096), timeout=8)
  58. if not data:
  59. print("RESULT: server closed connection (0 bytes)")
  60. return
  61. print(f"RESULT: got {len(data)} bytes")
  62. print(f" hex[:80]: {data[:80].hex()}")
  63. try:
  64. hdr, body = decode_frame(data)
  65. print(f" *** PARSED msg_id={hdr.msg_id} recog={hdr.recog} p1={hdr.param1} p2={hdr.param2} p3={hdr.param3}")
  66. print(f" body: {body[:200]!r}")
  67. if hdr.msg_id == 529:
  68. print(" *** *** SC 529 LOGIN KEY — LOGIN WORKS! *** ***")
  69. except Exception as e:
  70. print(f" (not a plaintext 24B frame: {e})")
  71. finally:
  72. writer.close()
  73. try:
  74. await writer.wait_closed()
  75. except Exception:
  76. pass
  77. async def main() -> None:
  78. uid, token = get_creds()
  79. print(f"uid={uid} token_len={len(token)}")
  80. print(f"gateway={GATEWAY}:{PROXY_PORT} sid={SERVER_ID} server_port={SERVER_PORT}")
  81. print()
  82. # otpType variants: "0" (none), "1"
  83. for otp in ("0", "1"):
  84. await attempt(uid, token, SERVER_ID, SERVER_PORT, otp)
  85. print()
  86. await asyncio.sleep(1)
  87. asyncio.run(main())