decode_dat.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. """Decode the .dat launch config (session 755, 62 bytes) + urlCreator.jsc strings.
  2. The .dat is likely the launch-parameter template cq.exe consumes."""
  3. import gzip
  4. import json
  5. from pathlib import Path
  6. import brotli
  7. def decode_response_bytes(path: Path) -> bytes:
  8. raw = path.read_bytes()
  9. idx = raw.find(b"\r\n\r\n")
  10. head = raw[:idx].decode("latin1")
  11. body = raw[idx + 4 :]
  12. enc = "br" if "Content-Encoding: br" in head else ("gzip" if "gzip" in head else "")
  13. chunked = "chunked" in head
  14. if chunked:
  15. out = b""
  16. rest = body
  17. while rest:
  18. le = rest.find(b"\r\n")
  19. if le < 0:
  20. break
  21. try:
  22. sz = int(rest[:le].split(b";")[0], 16)
  23. except ValueError:
  24. break
  25. if sz == 0:
  26. break
  27. out += rest[le + 2 : le + 2 + sz]
  28. rest = rest[le + 2 + sz + 2 :]
  29. body = out
  30. if enc == "br":
  31. body = brotli.decompress(body)
  32. elif enc == "gzip":
  33. body = gzip.decompress(body)
  34. return body
  35. raw_dir = Path(r"C:\Users\ADMINI~1\AppData\Local\Temp\opencode\saz_dec\raw")
  36. # 1. the .dat file (session 755)
  37. print("=== session 755: 20260804_cq.dat (62B) ===")
  38. dat = decode_response_bytes(raw_dir / "755_s.txt")
  39. print(f" raw hex: {dat.hex()}")
  40. print(f" raw repr: {dat!r}")
  41. try:
  42. print(f" as text: {dat.decode('utf-8')}")
  43. j = json.loads(dat)
  44. print(f" as json: {json.dumps(j, indent=2)}")
  45. except Exception:
  46. pass
  47. # try xxtea with the known key
  48. print()
  49. print("=== try XXTEA-decrypt the .dat ===")
  50. import struct
  51. import sys
  52. sys.path.insert(0, ".")
  53. from cq2_sdk.utils.encoding import encode6bit # noqa
  54. # maybe it's encoded with Encode6BitBuf
  55. try:
  56. dec = encode6bit(dat)
  57. print(f" encode6bit: {dec[:80]}")
  58. except Exception as e:
  59. print(f" encode6bit err: {e}")
  60. # simple XOR/reverse checks
  61. print(f" reversed hex: {dat[::-1].hex()}")
  62. print(f" as int32s: {list(struct.unpack('<' + 'i' * (len(dat) // 4), dat[:len(dat) // 4 * 4]))}")
  63. # 2. urlCreator.jsc strings
  64. print()
  65. print("=== urlCreator.jsc extractable strings ===")
  66. jsc = Path(r"C:\Users\ADMINI~1\AppData\Local\Temp\opencode\asar2\src\libs\urlCreator.jsc")
  67. if jsc.exists():
  68. data = jsc.read_bytes()
  69. import re
  70. for m in re.finditer(rb"[\x20-\x7e]{4,80}", data):
  71. print(f" {m.group().decode('ascii')}")
  72. else:
  73. print(" urlCreator.jsc missing")