"""DIMENSION 4 (duplicates), pass 3. Q2 is "what REQUEST does the duplicate flow emit". Request serializers in this client do NOT use string literals for keys: they call FUN_180180cd0() to turn an atom id into its wire name (proved by the CreatePack request serializer 0x180162530, which serialises atoms 0x20b, 0x369, 0x36b, 0xc4 that way). HYPOTHESIS: no serializer ever emits duplicateItemId (0xeb), duplicateItemIdList (0xec), duplicateItemLoans (0xed) or itemLoans (0x16f); they are response-only. METHOD / CONTROL: enumerate EVERY call site of FUN_180180cd0 from the reference manager, disassemble backwards up to 12 instructions in the same function, and record every immediate moved into ECX/RCX. Then assert the four control atoms 0x20b/0x369/0x36b/0xc4 ARE found (if the method cannot see known-present atoms it cannot be trusted to prove absence). Immediate forms handled: MOV ECX,imm and XOR ECX,ECX (zero) and LEA ECX,[imm]; anything unresolved is reported as UNKNOWN so absence is never inferred from a silent miss. Also: GetCardDuplicate script handler, and the owner of the item container. """ import traceback OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/store/dup3_out.txt" def w(fh, s=""): fh.write(str(s) + "\n") def dump(fh, a, label): s = dec(a) w(fh, "") w(fh, "#" * 70) w(fh, "# %s %#x len(src)=%d FULL" % (label, a, len(s))) w(fh, "#" * 70) w(fh, s) try: fh = open(OUT, "w") # ---------------- A: atom serialisation census ---------------- w(fh, "=" * 70) w(fh, "A. every call site of the atom->wire-name helper FUN_180180cd0") w(fh, "=" * 70) sites = [(frm, fn, ent) for frm, typ, fn, ent in xrefs_to(0x180180CD0) if "CALL" in typ] w(fh, "call sites: %d" % len(sites)) found = {} unknown = [] for frm, fn, ent in sites: ins = listing.getInstructionAt(addr(frm)) val = None cur = ins for _ in range(12): if cur is None: break cur = cur.getPrevious() if cur is None: break m = str(cur.getMnemonicString()).upper() ops = str(cur) if m == "MOV" and ops.upper().startswith("MOV ECX,"): t = ops.split(",")[1].strip() try: val = int(t, 16) if t.startswith("0x") else int(t) except ValueError: val = ("RAW", t) break if m == "XOR" and "ECX,ECX" in ops.upper().replace(" ", ""): val = 0 break if m == "CALL": break if isinstance(val, int): found.setdefault(val, []).append((frm, fn, ent)) else: unknown.append((frm, fn, ent, val)) w(fh, "resolved distinct atoms: %d ; unresolved sites: %d" % (len(found), len(unknown))) w(fh, "") w(fh, "CONTROLS (must be present): 0x20b=%s 0x369=%s 0x36b=%s 0xc4=%s" % ( 0x20B in found, 0x369 in found, 0x36B in found, 0xC4 in found)) w(fh, "TARGETS: 0xeb(duplicateItemId)=%s 0xec(duplicateItemIdList)=%s " "0xed(duplicateItemLoans)=%s 0x16f(itemLoans)=%s 0x16d(itemId)=%s" % ( 0xEB in found, 0xEC in found, 0xED in found, 0x16F in found, 0x16D in found)) for t in (0xEB, 0xEC, 0xED, 0x16F, 0x16D): if t in found: for frm, fn, ent in found[t]: w(fh, " atom %#x serialised at %#x in %s @ %#x" % (t, frm, fn, ent)) w(fh, "") w(fh, "-- all resolved atoms, sorted:") w(fh, " ".join("%#x" % k for k in sorted(found))) w(fh, "") w(fh, "-- UNRESOLVED call sites (absence claims must exclude these):") for frm, fn, ent, val in unknown: w(fh, " %#x in %s @ %#x last=%r" % (frm, fn, ent, val)) # ---------------- B: script handler ---------------- dump(fh, 0x180039FB0, "GetCardDuplicate script handler") dump(fh, 0x180039E10, "CONTROL: GetCardCategory script handler") # ---------------- C: who owns the item container ---------------- w(fh, "") w(fh, "=" * 70) w(fh, "C. writers/readers of the singleton pointer DAT_1802e6398") w(fh, "=" * 70) for frm, typ, fn, ent in xrefs_to(0x1802E6398): w(fh, " %#x %s in %s @ %#x" % (frm, typ, fn, ent)) fh.close() print("WROTE", OUT) except Exception: traceback.print_exc()