probe_auth_host.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. """Probe candidate AUTH hosts for 996box SMS endpoint.
  2. Found in 996box asar: phoneLoginCaptcha: '/authApi/auth/v1/login/byPhoneCode'
  3. Need to find the right host. Test:
  4. - auth.996hezi.com
  5. - auth-api.996hezi.com
  6. - box-auth.996hezi.com
  7. - api.jiyuhz.cn (existing password login host, unlikely but try)
  8. """
  9. import asyncio
  10. import json
  11. import sys
  12. from pathlib import Path
  13. _HERE = Path(__file__).resolve().parent
  14. sys.path.insert(0, str(_HERE.parent / "src"))
  15. from cq2_sdk.env_loader import load_env
  16. load_env(_HERE.parent / ".env")
  17. from cq2_sdk.login import Box996Login, ManualGeetestSolver
  18. CANDIDATE_HOSTS = [
  19. "https://auth.996hezi.com",
  20. "https://auth-api.996hezi.com",
  21. "https://box-auth.996hezi.com",
  22. "https://auth.box.996hezi.com",
  23. "https://api.996hezi.com", # 之前没用过这个
  24. "https://api.jiyuhz.cn", # 已知是密码登录的 v3
  25. ]
  26. PATH = "/authApi/auth/v1/login/byPhoneCode"
  27. async def probe(host: str) -> dict:
  28. """Returns dict with status, code, msg, signature_present."""
  29. box = Box996Login(geetest=ManualGeetestSolver(), device_id="00:15:5d:0a:04:00")
  30. try:
  31. r = await box._request(
  32. "POST", host, PATH,
  33. json_body={"phone": "13800138000",
  34. "channel_id": "", "game_id": "",
  35. "inviter_uid": "", "needConfirmLogin": True},
  36. )
  37. code = r.get("code", 0) if isinstance(r, dict) else 0
  38. msg = r.get("msg", "") if isinstance(r, dict) else ""
  39. return {"host": host, "http": 200, "code": code, "msg": msg[:80],
  40. "suspicious": "请先登录" in msg or msg == ""}
  41. except Exception as e:
  42. from cq2_sdk.login.box_996 import Box996Error
  43. msg = str(e)[:120]
  44. if isinstance(e, Box996Error):
  45. return {"host": host, "http": 200, "code": e.code, "msg": e.msg[:80],
  46. "suspicious": "请先登录" in e.msg}
  47. return {"host": host, "http": 0, "code": 0, "msg": msg,
  48. "suspicious": False}
  49. async def main() -> int:
  50. print(f"Probing {len(CANDIDATE_HOSTS)} candidate hosts for {PATH}\n")
  51. results = []
  52. for host in CANDIDATE_HOSTS:
  53. r = await probe(host)
  54. results.append(r)
  55. marker = ""
  56. if r["http"] == 200 and not r["suspicious"]:
  57. marker = "[!!! REAL !!!]"
  58. elif r["http"] == 200 and r["suspicious"]:
  59. marker = "[needs auth]"
  60. elif r["http"] == 0:
  61. marker = "[unreachable]"
  62. else:
  63. marker = f"[http={r['http']}]"
  64. print(f" {marker:<16} {host:<35} http={r['http']} code={r.get('code', 0):>4} {r.get('msg', '')}")
  65. print()
  66. real = [r for r in results if r["http"] == 200 and not r["suspicious"]]
  67. if real:
  68. print(f"[!!!] {len(real)} host(s) returned a non-auth-required response:")
  69. for r in real:
  70. print(f" {r['host']} code={r['code']} msg={r['msg']}")
  71. else:
  72. print("[!] No host returned a non-auth response. May need to dig deeper.")
  73. return 0
  74. if __name__ == "__main__":
  75. sys.exit(asyncio.run(main()))