"""VERIFY-4. Re-run the failed census with a WORKING method, plus the remaining actionable D5 claims. WHY A RERUN: q_pack_v2_3's census used Instruction.getScalar(), which returns null for the displacement inside a memory operand. Its own control (FUN_18002c3c0, known to read +0x144..+0x154) scored ZERO, so the technique was void and no absence could be concluded from it. Here I match against the printed operand text instead, which shows the displacement whatever its encoding (disp8, disp32, SIB, LEA). H11 nothing besides the known lifecycle+adapter set touches +0x144..+0x154. H12 FutCreatePackServerResponse+0x28 (numberItems) is read by nothing. H17 FUN_18002cc90 early-returns when tile+0x6c == -1. H18 PurchaseItems req serializer 0x180126440 + URL builder 0x180126720. H19 FUN_1801267b0 turns 409 + "User already has a transaction" into 0x70. H20 purchaseitems response deser field map. H21 the pack element's firstPartyStoreId call target qword[0x1801e51d0] is atoi. CONTROL: the census must list FUN_18002c3c0 with all five offsets, and must list the pack-record copy-assign 0x1801340e0 and uninit-copy 0x180133210. If those three are missing the census is broken again. """ import traceback, re from collections import defaultdict OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres/" try: PAT = re.compile(r"0x(144|148|14c|150|154)\b") hits = defaultdict(set); sites = defaultdict(list) ninst = 0; nfun = 0 fi = fm.getFunctions(True) while fi.hasNext(): f = fi.next(); nfun += 1 ent = int(f.getEntryPoint().getOffset()) it = listing.getInstructions(f.getBody(), True) while it.hasNext(): ins = it.next(); ninst += 1 s = str(ins) m = PAT.findall(s) if m: for v in m: hits[ent].add(int(v, 16)) if len(sites[ent]) < 10: sites[ent].append("%010x %s" % (int(ins.getAddress().getOffset()), s)) print("=" * 74) print("H11 CENSUS (operand-text method). functions=%d instructions=%d" % (nfun, ninst)) ranked = sorted(hits.items(), key=lambda kv: (-len(kv[1]), kv[0])) ctl = {0x18002c3c0, 0x1801340e0, 0x180133210} print(" CONTROLS: " + ", ".join("%010x=%d offsets" % (c, len(hits.get(c, ()))) for c in sorted(ctl))) print(" functions with >=4 of the five offsets:") for e, s in ranked: if len(s) < 4: break print(" %010x n=%d %s" % (e, len(s), sorted(hex(x) for x in s))) for t in sites[e]: print(" ", t) print(" functions with exactly 3: %s" % ["%010x" % e for e, s in ranked if len(s) == 3]) print(" functions with exactly 2: %d, with exactly 1: %d" % (sum(1 for _, s in ranked if len(s) == 2), sum(1 for _, s in ranked if len(s) == 1))) with open(OUT + "v4_census.txt", "w") as fh: for e, s in ranked: fh.write("%010x n=%d %s\n" % (e, len(s), sorted(hex(x) for x in s))) for t in sites[e]: fh.write(" %s\n" % t) print(" full census -> " + OUT + "v4_census.txt") print() print("=" * 74) print("H12 hunt the FutCreatePackServerResponse consumer") print(" callers of ServerCall ctor 0x1801623d0:", xrefs_to(0x1801623d0)) print(" callers of pool builder 0x18010cdc0:", xrefs_to(0x18010cdc0)[:10]) for s in (b"OnPurchasePackResponse", b"OnCreatePackResponse", b"PurchasePack", b"OnPackPurchase", b"CREATEPACK\x00"): h = find_all(s) print(" string %r at %s" % (s, ["%010x" % a for a in h])) for a in h: for r in xrefs_to(a): print(" xref %010x %s in %s" % (r[0], r[1], r[2])) print() print("=" * 74) print("H17/H18/H19/H20 decompiles") for e, tag in [(0x18002cc90, "price_formatter"), (0x180126440, "purchaseitems_reqser"), (0x180126720, "purchaseitems_url"), (0x1801267b0, "purchaseitems_httperr"), (0x180126900, "purchaseitems_state1body")]: s = dec(e) open(OUT + "v4_%s_%x.txt" % (tag, e), "w").write(s) print() print("---- %s %#x len=%d lines=%d ----" % (tag, e, len(s), s.count("\n"))) print(s if len(s) < 4200 else s[:4200] + "\n...TRUNCATED, full text in file...") print() print("=" * 74) print("H20 purchaseitems_deser 0x1801269f0 ladder (raw asm, dispatch region)") f = func(0x1801269f0) it = listing.getInstructions(f.getBody(), True) lines = [] while it.hasNext(): i = it.next() lines.append("%010x %s" % (int(i.getAddress().getOffset()), str(i))) open(OUT + "v4_purchaseitems_deser.asm", "w").write("\n".join(lines) + "\n") for l in lines: a = int(l[:10], 16) if 0x180126ab0 <= a <= 0x180126e60: print(" " + l) print() print("=" * 74) print("H21 import at 0x1801e51d0") t = qword(0x1801e51d0) print(" qword[0x1801e51d0] = %016x" % t) d = listing.getDataAt(addr(0x1801e51d0)) print(" ghidra data/label:", d.getLabel() if d else None, [str(s) for s in prog.getSymbolTable().getSymbols(addr(0x1801e51d0))]) except Exception: traceback.print_exc()