# -*- coding: utf-8 -*- """ADVERSARIAL VERIFY 5. A. THE LADDER. My immediate-scan in q_pack_v3_4 FAILED ITS OWN CONTROL: neither 0x23f (a case Ghidra shows in 0x18013fe00) nor 0x20e (a case in 0x18013c6d0) exists as a raw immediate. That proves the dispatch is a running SUB/DEC ladder and that any "grep for the constant" method is invalid here. So: dump the FULL disassembly of 0x18013fe00 and reconstruct the ladder from the SUB/JZ chain, validating the reconstruction against the 52 arms Ghidra's decompiler reports. Only if the reconstruction reproduces those 52 do I get to say anything about 0x23d. B. Who WRITES pack-definition +0xc0..+0xd0? D4 claim 13 grades the NUM_*_IN_PACK fields authority=SERVER but its evidence only shows the READ. Find every function that writes ALL of 0xc0/0xc4/0xc8/0xcc/0xd0 as dwords, and the callers of FUN_180015d80 so param_4 can be identified. C. CARDS_CB_ERR_PACK_NOT_IN_DIME xref (the D6 open lead). q4 crashed here because I passed blocks=None to find_all; fixed. """ import traceback, re OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres" def dump(n, s): p = "%s/v_%s.txt" % (OUT, n) open(p, "w").write(s) print("[wrote %s %d chars]" % (p, len(s))) try: from ghidra.program.model.address import AddressSet print("=" * 78) print("A: full disassembly of 0x18013fe00, and ladder reconstruction") f6 = func(0x18013fe00) it = listing.getInstructions(f6.getBody(), True) lines = [] insns = [] while it.hasNext(): ins = it.next() a = int(ins.getAddress().getOffset()) lines.append("%#x %s" % (a, ins)) insns.append((a, ins.getMnemonicString(), str(ins))) dump("q5_item_deser_disasm", "\n".join(lines)) print(" %d instructions" % len(insns)) # ladder: SUB reg,imm (or DEC reg) whose NEXT instruction is a conditional jump acc = {} atoms = [] for i, (a, mn, t) in enumerate(insns): nxt = insns[i + 1][1] if i + 1 < len(insns) else "" m = re.match(r"^(SUB|CMP|DEC|MOV)\s+([A-Z0-9]+),?\s*(.*)$", t) if not m: continue op, reg, rest = m.group(1), m.group(2), m.group(3) imm = None mi = re.match(r"^(0x[0-9a-fA-F]+|\d+)$", rest.strip()) if mi: imm = int(mi.group(1), 0) if op == "MOV": # a fresh load of the dispatch register resets the running sum acc[reg] = 0 continue if op == "DEC": imm = 1 rest = "1" if imm is None: continue cond = nxt.startswith("J") and nxt not in ("JMP",) if op == "SUB": acc[reg] = acc.get(reg, 0) + imm if cond: atoms.append((a, acc[reg], reg, t, nxt)) elif op == "CMP": if cond: atoms.append((a, acc.get(reg, 0) + imm, reg, t, nxt)) vals = sorted(set(v for _, v, _, _, _ in atoms)) s6 = dec(0x18013fe00) cases = sorted(set(int(x, 16) for x in re.findall(r"case 0x([0-9a-f]+):", s6))) print(" reconstructed ladder values (%d): %s" % (len(vals), [hex(v) for v in vals])) print(" decompiler case arms (%d): %s" % (len(cases), [hex(c) for c in cases])) inter = sorted(set(vals) & set(cases)) print(" RECONSTRUCTION CONTROL: %d/%d decompiler arms reproduced" % (len(inter), len(cases))) print(" arms the ladder found that the decompiler did not: %s" % [hex(v) for v in sorted(set(vals) - set(cases))][:60]) print(" 0x23d in reconstructed ladder? ", 0x23d in vals) print(" 0x23f in reconstructed ladder? ", 0x23f in vals) print(" --- ladder trace ---") for a, v, reg, t, nxt in atoms: print(" %#x atom=%#-6x %-28s next=%s" % (a, v, t, nxt)) print("=" * 78) print("B: functions writing dwords at +0xc0/+0xc4/+0xc8/+0xcc/+0xd0") blk = [b for b in mem.getBlocks() if b.getName() == ".text"][0] it = listing.getInstructions(AddressSet(blk.getStart(), blk.getEnd()), True) per = {} rx = re.compile(r"MOV\s+dword ptr \[([A-Z0-9]+) \+ (0x(?:c0|c4|c8|cc|d0))\]") while it.hasNext(): ins = it.next() t = str(ins) m = rx.match(t) if not m: continue a = int(ins.getAddress().getOffset()) per.setdefault(fname(a), set()).add(m.group(2)) full = [(k, sorted(v)) for k, v in per.items() if len(v) >= 4] print(" functions writing >=4 of the five: %d" % len(full)) for k, v in full: print(" %-26s %s" % (k, v)) print(" callers of FUN_180015d80:") try: for c in callers(0x180015d80): print(" ", c) except Exception as e: print(" EXC", e) print(" xrefs_to(0x180015d80):") try: for r in xrefs_to(0x180015d80): print(" ", r) except Exception as e: print(" EXC", e) print("=" * 78) print("C: CARDS_CB_ERR_PACK_NOT_IN_DIME") hits = find_all(b"CARDS_CB_ERR_PACK_NOT_IN_DIME") print(" string sites:", [hex(int(h)) for h in hits]) for h in hits: for r in xrefs_to(int(h)): a = r[0] if isinstance(r, tuple) else int(r) print(" xref %s in %s" % (r, fname(a))) se = dec(a) dump("q5_dime_%s" % (fname(a) or "unk"), se) print(" ---- %s %d chars ----" % (fname(a), len(se))) print(se) except Exception: traceback.print_exc() print("QUERY DONE")