cdp_recon.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. """Drive 996box via CDP (Chrome DevTools Protocol):
  2. 1. Connect to the login page (pc.hzwlan.com/login/account)
  3. 2. Inspect the login form (field names/selectors)
  4. 3. Screenshot for visual confirmation
  5. Does NOT submit yet — recon only (we need the exact selectors first).
  6. """
  7. import asyncio
  8. import base64
  9. import json
  10. import sys
  11. import httpx
  12. import websockets
  13. async def get_targets():
  14. async with httpx.AsyncClient(timeout=5) as c:
  15. r = await c.get("http://127.0.0.1:9222/json/list")
  16. return r.json()
  17. async def cdp_eval(ws_url: str, expr: str) -> dict:
  18. async with websockets.connect(ws_url, max_size=10 * 1024 * 1024) as ws:
  19. await ws.send(json.dumps({
  20. "id": 1,
  21. "method": "Runtime.evaluate",
  22. "params": {"expression": expr, "returnByValue": True},
  23. }))
  24. while True:
  25. msg = json.loads(await ws.recv())
  26. if msg.get("id") == 1:
  27. return msg.get("result", {})
  28. async def cdp_screenshot(ws_url: str, path: str) -> None:
  29. async with websockets.connect(ws_url, max_size=10 * 1024 * 1024) as ws:
  30. await ws.send(json.dumps({"id": 2, "method": "Page.captureScreenshot", "params": {"format": "png"}}))
  31. while True:
  32. msg = json.loads(await ws.recv())
  33. if msg.get("id") == 2:
  34. data = msg["result"]["data"]
  35. with open(path, "wb") as f:
  36. f.write(base64.b64decode(data))
  37. return
  38. async def main():
  39. targets = await get_targets()
  40. login_page = next((t for t in targets if "login" in t.get("url", "")), None)
  41. if not login_page:
  42. print("no login page target found")
  43. for t in targets:
  44. print(f" [{t['type']}] {t['url'][:80]}")
  45. return 1
  46. ws_url = login_page["webSocketDebuggerUrl"]
  47. print(f"login page: {login_page['url']}")
  48. print(f"ws: {ws_url[:60]}...")
  49. print()
  50. # 1. Recon: form fields
  51. print("=== form recon ===")
  52. expr = """
  53. (function() {
  54. const inputs = Array.from(document.querySelectorAll('input')).map(i => ({
  55. tag: 'input', type: i.type, name: i.name, id: i.id,
  56. placeholder: i.placeholder, cls: i.className.slice(0,40),
  57. visible: i.offsetParent !== null
  58. }));
  59. const buttons = Array.from(document.querySelectorAll('button, [role=button], .btn, a[class*=btn]')).slice(0,12).map(b => ({
  60. tag: b.tagName, text: (b.innerText||'').trim().slice(0,30),
  61. cls: (b.className||'').toString().slice(0,40), id: b.id,
  62. visible: b.offsetParent !== null
  63. }));
  64. return JSON.stringify({inputs, buttons}, null, 1);
  65. })()
  66. """
  67. res = await cdp_eval(ws_url, expr)
  68. val = res.get("result", {}).get("value", "")
  69. if val:
  70. data = json.loads(val)
  71. print("--- inputs ---")
  72. for i in data["inputs"]:
  73. vis = "OK " if i["visible"] else "hid"
  74. print(f" [{vis}] type={i['type']:<10} name={i['name']:<16} id={i['id']:<20} ph={i['placeholder'][:20]}")
  75. print("--- buttons ---")
  76. for b in data["buttons"]:
  77. vis = "OK " if b["visible"] else "hid"
  78. print(f" [{vis}] {b['tag']:<8} '{b['text']}' cls={b['cls'][:30]}")
  79. else:
  80. print("eval failed:", json.dumps(res)[:300])
  81. # 2. Screenshot
  82. await cdp_screenshot(ws_url, "cdp_login_page.png")
  83. print("\nscreenshot: cdp_login_page.png")
  84. return 0
  85. sys.exit(asyncio.run(main()))