#!/usr/bin/env python3 """Diff the atoms the userInfo deserializer (0x18013ec10) can consume against the keys utas_server.user_info() actually sends, and flag STRING-typed fields we omit (a NULL string pointer is exactly the crash class seen in FUN_180084f90).""" import re, sys, os sys.path.insert(0, "/home/alex/Documents/OpenFUT/fifa17-recon/tools") os.environ.setdefault("FUT_PROFILE", "/tmp/claude-1000/-home-alex-Documents-OpenFUT/" "4cf26d25-8cee-4db3-ad9e-9fd1838020eb/scratchpad/diffprof.json") atoms = {} for line in open("/home/alex/Documents/OpenFUT/fifa17-recon/docs/fut_atoms.tsv"): p = line.rstrip("\n").split("\t") if len(p) >= 3: atoms[int(p[0])] = p[2] src = open("/tmp/ghidra_fut/userinfo.txt").read() # Every comparison against the key-id variable, plus switch cases. ids = set() for m in re.finditer(r"iVar\d+ == (0x[0-9a-f]+|\d+)", src): ids.add(int(m.group(1), 0)) for m in re.finditer(r"case (0x[0-9a-f]+|\d+):", src): ids.add(int(m.group(1), 0)) for m in re.finditer(r"caseD_([0-9a-f]+)", src): ids.add(int(m.group(1), 16)) # getter used per id -> type. 0x1801c7aa0 = STRING, 0x1801c79d0 = int, # 0x1801c7a40/0x1801c7b40 = bool/other scalars. GET = {"1801c7aa0": "str", "1801c79d0": "int"} typed = {} for m in re.finditer(r"(?:iVar\d+ == |case )(0x[0-9a-f]+|\d+)\)?:?\s*\{?\s*\n((?:.*\n){0,6})", src): try: i = int(m.group(1), 0) except ValueError: continue blk = m.group(2) for g, t in GET.items(): if g in blk: typed[i] = t break from utas_server import user_info # noqa: E402 sent = set(user_info().keys()) known = {i: atoms.get(i, "?") for i in sorted(ids) if i in atoms} print("userInfo deser consumes %d named atoms; user_info() sends %d keys\n" % (len(known), len(sent))) missing = [(i, n, typed.get(i, "")) for i, n in known.items() if n not in sent] extra = sorted(sent - set(known.values())) print("=== parsed by the client but NOT sent by us (%d) ===" % len(missing)) for i, n, t in sorted(missing, key=lambda x: (x[2] != "str", x[1])): print(" %-32s atom %#-6x %s" % (n, i, ("<-- STRING" if t == "str" else t))) print("\n=== we send but the deser does not name (harmless SKIPs) ===") print(" " + ", ".join(extra))