"""D2 QUICK SELL, batch 4: settle where the "level" query key comes from. MEASURED FACT (live memory, pid 134663, read-only): the fcc_discardcoins table has 141 rows keyed (cardtype, level, rare) with level in {1,2,3} only -- there is NO level==0 row. Three live club items decode exactly: cardtype 1, level 3, rare 1 -> price 800 ; rating 94 -> 752 ; rating 75 -> 600 cardtype 6, level 1, rare 0 -> price 5 ; rating 55 -> 3 cardtype 6, level 3, rare 0 -> price 40 ; rating 95 -> 38 So the query MUST have been issued with level = 3 / 1 / 3, never 0. But batch 2's instruction scan of FUN_18013fe00 found EXACTLY ONE reference to [RBP + 0x1b4] (the slot the "level" argument is loaded from) and it is a READ at 0x180141099; the only write covering that slot appeared to be the 16-byte MOVDQA at 0x18013ffa1. Something is wrong with that conclusion -- this is exactly the absence trap. Find the write. HYPOTHESES TO TEST, in order H1 the MOVDQA source is not _DAT_1801f66a0, or that constant is not 56 01 00 00 | 00 00 00 00 | ... H2 part of the atom switch lives outside the address set Ghidra assigned to FUN_18013fe00, so the body-only instruction walk missed an arm. Test by walking the whole address range 0x18013fe00..0x180141400 instruction by instruction, ignoring function boundaries. H3 the slot is written through a register-based pointer (LEA RAX,[RBP+0x160] style) rather than an RBP displacement. CONTROL: the same range-walk must find the KNOWN write to [RBP + 0x1ac] (cardtype) at 0x180140e16 and the KNOWN write to [RBP + 0x1b8] (rareflag) at 0x180140cc5. Both are plain RBP-displacement MOVs, the same syntactic form as the write being hunted, so finding them proves the walk sees this form. """ import traceback try: print("##### H1: the initialiser constant #####") for a in (0x1801f66a0, 0x1801f66b0): print(" %#x = %s" % (a, read_bytes(a, 16).hex())) print(" asm 0x18013fe00..0x18013fff0:") p = 0x18013fe00 while p < 0x18013fff0: i = listing.getInstructionAt(addr(p)) if i is None: p += 1 continue print(" %#x %s" % (p, str(i))) p += i.getLength() print("\n##### H2/H3: whole-range instruction walk 0x18013fe00..0x180141400 #####") want = ("0x1b4", "0x1b0", "0x1ac", "0x1b8", "0x214", "0x198", "0x19c") p = 0x18013fe00 n = 0 hits = {w: [] for w in want} lea160 = [] while p < 0x180141400: i = listing.getInstructionAt(addr(p)) if i is None: p += 1 continue t = str(i) n += 1 for w in want: if w in t: hits[w].append((p, t)) if "RBP + 0x160]" in t or "RBP + 0x1" in t and t.startswith("LEA"): lea160.append((p, t)) p += i.getLength() print(" walked %d instructions" % n) for w in want: print(" --- '%s' : %d ---" % (w, len(hits[w]))) for a, t in hits[w]: print(" %#x %s" % (a, t)) print(" --- LEA of frame slots ---") for a, t in lea160: print(" %#x %s" % (a, t)) print("\n##### the atom-0x191 (level) question #####") # find every immediate 0x191 anywhere in the range, in any form p = 0x18013fe00 while p < 0x180141400: i = listing.getInstructionAt(addr(p)) if i is None: p += 1 continue t = str(i) if "0x191" in t or "0x18a" in t or "0x192" in t: print(" %#x %s" % (p, t)) p += i.getLength() print("\n##### callers of FUN_18013fe00 (maybe one pre-fills level) #####") for frm, typ, fn, ent in xrefs_to(0x18013fe00): print(" %#x %s %s %#x" % (frm, typ, fn, ent)) except Exception: traceback.print_exc()