"""VERIFY-1. Adversarial re-derivation of the pack element deserializer. HYPOTHESES UNDER ATTACK (from D3/D5 reports): H1 0x18013af30 parses packContentInfo (atom 0x20c) INLINE with EXACTLY five children: 0x170,0x149,0x2c6,0x63,0x273 -> rec+0x144..+0x154. H2 atoms 0x2e3 (start) and 0x35d (unopened) are TOP-LEVEL, not inside 0x20c. H3 atoms 0x15c,0x26b,0x298,0x20f,0x176 have REAL arms (not SKIP). H4 record stride 0x158, and a CMP against 0x64 caps the store at 100 packs. H5 firstPartyStoreId (0x127) in the PACK element uses the STR getter 0x1801c7aa0 + atoi, NOT the INT getter. METHOD DELIBERATELY DIFFERENT FROM THE ORIGINALS: I dump the FULL RAW DISASSEMBLY of the function (every instruction, address + mnemonic + operands) and analyse the ladder from bytes/asm, not from the decompiler's frame locals. I also cross-check with the decompile but the asm is primary. CONTROL: the function must contain a call to the known SKIP primitive 0x180135ff0 and to the known INT/BOOL/STR primitives; and the FNV hasher 0x180180d00 must disassemble to the known prologue. """ import traceback, sys OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres/" try: def dump_asm(entry, path, label): f = func(entry) if f is None: print("NO FUNCTION at %#x" % entry); return None body = f.getBody() lines = [] it = listing.getInstructions(body, True) n = 0 while it.hasNext(): ins = it.next() a = int(ins.getAddress().getOffset()) lines.append("%010x %-8s %s" % (a, ins.getMnemonicString(), str(ins).split(None, 1)[1] if ' ' in str(ins) else '')) n += 1 open(path, "w").write("\n".join(lines) + "\n") print("[%s] %s entry=%#x instructions=%d bodysize=%#x -> %s" % (label, f.getName(), int(f.getEntryPoint().getOffset()), n, int(body.getNumAddresses()), path)) return lines print("=" * 78) print("CONTROL: FNV hasher prologue at 0x180180d00") print("bytes:", read_bytes(0x180180d00, 16).hex()) f = func(0x180180d00) print("ghidra fn:", f.getName() if f else None) print() print("=" * 78) print("PACK ELEMENT DESERIALIZER 0x18013af30") src = dec(0x18013af30) open(OUT + "v1_packelem_dec.txt", "w").write(src) print("decompile len(src) =", len(src), " lines =", src.count("\n")) lines = dump_asm(0x18013af30, OUT + "v1_packelem.asm", "packelem") # ---- ladder reconstruction from ASM ---- # Find every CMP/SUB against an immediate in the atom range, in address order, # together with the following conditional jump target. print() print("--- ATOM LADDER (SUB/CMP against immediates, address order) ---") f = func(0x18013af30) it = listing.getInstructions(f.getBody(), True) seq = [] while it.hasNext(): ins = it.next() m = ins.getMnemonicString() if m in ("SUB", "CMP", "ADD"): try: sc = ins.getScalar(1) except Exception: sc = None if sc is not None: v = int(sc.getUnsignedValue()) if 1 <= v <= 0x400: seq.append((int(ins.getAddress().getOffset()), m, str(ins), v)) run = 0 for a, m, s, v in seq: if m == "SUB": run += v elif m == "CMP": run += v print("%010x %-40s imm=%#x running=%#x" % (a, s, v, run)) print() print("--- CALLS to known primitives, with address ---") PRIM = {0x1801c79d0: "INT", 0x1801c7620: "BOOL", 0x1801c7aa0: "STR", 0x180135ff0: "SKIP", 0x1801c7f10: "NEXTTOK", 0x1801c8270: "BEGINOBJ", 0x18013fe00: "ITEMDESER", 0x1800d7af0: "clampI32", 0x1800d7b30: "clampNonNegI32", 0x1800d7b10: "toU16", 0x180138bd0: "CURRENCYELEM", 0x180139070: "FINALPRICE", 0x18013aae0: "ORIGPRICE"} it = listing.getInstructions(f.getBody(), True) while it.hasNext(): ins = it.next() if ins.getMnemonicString() == "CALL": for r in ins.getFlows(): t = int(r.getOffset()) if t in PRIM: print("%010x CALL %-14s (%#x)" % (int(ins.getAddress().getOffset()), PRIM[t], t)) print() print("--- STRIDE / CAP evidence: instructions between 0x18013bad0 and 0x18013bb60 ---") a = 0x18013ad0 and 0x18013bad0 while a < 0x18013bb60: ins = listing.getInstructionAt(addr(a)) if ins is None: a += 1; continue print("%010x %s" % (a, str(ins))) a += ins.getLength() print() print("=" * 78) print("PACK RECORD CTOR 0x1801342d0") src2 = dec(0x1801342d0) open(OUT + "v1_packctor_dec.txt", "w").write(src2) print("len =", len(src2)) print(src2) dump_asm(0x1801342d0, OUT + "v1_packctor.asm", "packctor") except Exception: traceback.print_exc()