bruteforce_sig.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. """Brute-force the exact HMAC input format by trying variants.
  2. Takes ONE captured request (session 762 — smallest body) and tries dozens
  3. of combinations: url with/without scheme, body with/without trailing newline,
  4. token placement, deviceType value, etc. Prints any MATCH.
  5. """
  6. import hashlib
  7. import hmac
  8. import json
  9. import re
  10. from pathlib import Path
  11. from urllib.parse import unquote, urlparse
  12. SAZ_RAW = Path(r"C:\Users\ADMINI~1\AppData\Local\Temp\opencode\saz_dec\raw")
  13. SID = "762" # riskCheck: small clean body
  14. KEY = "BB0AAAC906FC4B7CADB116A213D46689"
  15. UA = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) 996Box/5.1.1 Chrome/108.0.5359.215 Electron/22.3.4 Safari/537.36"
  16. DEVICE_ID = "00:15:5d:0a:04:00"
  17. raw = (SAZ_RAW / f"{SID}_c.txt").read_bytes().decode("utf-8", errors="replace")
  18. first = raw.split("\n", 1)[0]
  19. method, full_url = re.match(r"(GET|POST)\s+(\S+)", first).groups()
  20. auth = re.search(r"NONCE=([^;]+);TIMESTAMP=(\d+);SIGNATURE=([0-9a-f]+)", raw)
  21. NONCE, TS, EXPECTED = auth.group(1), auth.group(2), auth.group(3)
  22. token_m = re.search(r"^token:\s*(\S+)", raw, re.MULTILINE)
  23. TOKEN = token_m.group(1) if token_m else ""
  24. sep = "\r\n\r\n" if "\r\n\r\n" in raw else "\n\n"
  25. WIRE_BODY = raw.split(sep, 1)[1].strip() if sep in raw else ""
  26. print(f"target sig: {EXPECTED}")
  27. print(f"body: {WIRE_BODY[:200]}")
  28. print()
  29. parsed = urlparse(full_url)
  30. path_with_qs = parsed.path + ("?" + parsed.query if parsed.query else "")
  31. # Body variants
  32. body_variants = {
  33. "wire_body": WIRE_BODY,
  34. "wire_body_trailing_nl": WIRE_BODY + "\n",
  35. "parsed_json_compact": None,
  36. "empty": "",
  37. "none": None,
  38. }
  39. try:
  40. d = json.loads(WIRE_BODY)
  41. body_variants["parsed_json_compact"] = json.dumps(d, separators=(",", ":"))
  42. except Exception:
  43. pass
  44. url_variants = {
  45. "full": full_url,
  46. "path_qs": path_with_qs,
  47. "path_only": parsed.path,
  48. }
  49. token_variants = {"real": TOKEN, "empty": ""}
  50. results = []
  51. for uname, url in url_variants.items():
  52. for bname, body in body_variants.items():
  53. for tname, tok in token_variants.items():
  54. for devtype in ("pc", "PC", "windows"):
  55. lines = [method, url, TS, NONCE, devtype, DEVICE_ID, "5.1.1.9007", tok, UA]
  56. if body is None:
  57. lines.append("")
  58. else:
  59. lines.append(body)
  60. for joiner_tail in ("\n",):
  61. value = "\n".join(lines) + joiner_tail
  62. sig = hmac.new(KEY.encode(), value.encode(), hashlib.sha256).hexdigest()
  63. if sig == EXPECTED:
  64. results.append((uname, bname, tname, devtype, "FOUND", value))
  65. print(f"*** MATCH: url={uname} body={bname} token={tname} devtype={devtype}")
  66. print(f"value repr:\n{repr(value)}")
  67. if not results:
  68. print("no match in variant space; try body-order or UA differences")
  69. # extra: maybe UA differs? try box-agent header value
  70. print("Expected:", EXPECTED)