"""DIMENSION 3 SEASONS q4. ESTABLISHED: SeasonList deser 0x1801683f0 clears+repopulates the model season-list vector (model vtable +0x898). FUN_180057330 reads that vector; empty -> NOSEASONS. NOW: (a) confirm +0x898 getter returns this+0x5c68 and +0x588 getter -> this+0x7138; (b) find WHO ISSUES the GET /season (SEASONLIST) RPC and its callers -- is the request reachable, or is it never issued; (c) find every writer of the count short at this+0x7138+0x96/+0x98 via a disp32 scan (form-independent). CONTROL for disp32 scan: also scan for a KNOWN-written model offset (0x1fd2e, the trading gate byte, known to have exactly one writer FUN_18011dc50) -> must find >=1 hit, else the scan form is broken. """ import traceback, struct try: MODEL_VT = 0x18021c2a0 print("### model vtable getters ###") for slot in (0x588, 0x898, 0x850): t = qword(MODEL_VT + slot) print("slot +%#x -> %#x %s" % (slot, t, fname(t))) print(dec(t)[:600]) print("-" * 40) def disp32_scan(off, label, blocks=(".text",)): le = struct.pack("", len(hits), "hits") for h in hits: f = fm.getFunctionContaining(addr(h)) print(" ", hex(h), f.getName() if f else "?") return hits print("\n### disp32 scans (form-independent) ###") disp32_scan(0x1fd2e, "CONTROL trading gate byte") disp32_scan(0x5c68, "season list vector base") disp32_scan(0x7138, "season sub-struct base") # the +0x96 / +0x98 short lives INSIDE the +0x7138 struct; its writers deref a # pointer to that struct then +0x96. Hard to disp32-scan directly; instead show # readers/writers of the +0x7138 getter result are the callers of slot +0x588. # SEASONLIST RPC: descriptor row 69, stride 0x30, base 0x1802caa28 print("\n### RPC descriptor row 69 (SEASONLIST) ###") base = 0x1802caa28 row = base + 69 * 0x30 print("row addr", hex(row), "bytes:", read_bytes(row, 0x30).hex()) # first qword often a name ptr, look for a char* to 'season' for o in range(0, 0x30, 8): v = qword(row + o) s = "" if 0x180000000 <= v < 0x181000000: try: s = rd_str(v, 40) except Exception: s = "" print(" +%#x %#x %r" % (o, v, s)) # find the 'ut/%s/season' or 'season' URL template and its xref (the issuer) print("\n### 'season' url template search ###") for lit in (b"ut/%s/season\x00", b"/season\x00", b"season\x00"): hits = find_all(lit, blocks=(".rdata",)) print(" ", lit, "->", [hex(h) for h in hits][:8]) for h in hits[:4]: for x in xrefs_to(h): print(" xref", hex(x[0]), x[2], hex(x[3])) sys.stdout.flush() os._exit(0) except Exception: traceback.print_exc() sys.stdout.flush() os._exit(0)