# -*- coding: utf-8 -*- """ q_pack_inv_10 -- DIMENSION 1 pass 10: the READERS of the unopenedPacks total. CHAIN ESTABLISHED SO FAR userInfo.unopenedPacks{preOrderPacks,recoveredPacks} -> FUN_18013ec10 sums them and calls model->vtbl[0x4e0] @0x18013f223 -> FUN_18011e120 stores the sum at model+0x20950 and broadcasts event 0x273d A byte scan of .text (modrm mod=10, disp32 == 0x20950) finds exactly THREE accesses: 0x18011e131 the setter itself 0x18011c202 inside 0x18011c1f0, which is vtable slot +0x4e8 -> the GETTER 0x18010e06d the only other reader and the event id 0x273d appears at 0x18011e159 (the broadcast) plus 0x1800b3946, 0x18007e861, 0x180199e08. HYPOTHESIS: those four addresses are the complete client-side consumer set. CONTROLS * class_deser("FutSquadSaveServerResponse") -> 0x180171a60. * 0x18011c1f0 must be vtable(0x18021c2a0) slot +0x4e8 (it is, per the live read), and its body must READ +0x20950 -- if it writes, the getter/setter call is inverted and the reader analysis is void. """ import traceback OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres" try: got = sorted(set(x[0] for x in class_deser("FutSquadSaveServerResponse"))) print("CONTROL FutSquadSaveServerResponse -> %s %s" % ([hex(g) for g in got], "PASS" if 0x180171A60 in got else "FAIL")) print("CONTROL vtable+0x4e8 = %#x (expect 0x18011c1f0)" % qword(0x18021C2A0 + 0x4E8)) for va, tag in ((0x18011C1F0, "getter_4e8"), (0x18010E06D, "reader_18010e06d"), (0x1800B3946, "evt_1800b3946"), (0x18007E861, "evt_18007e861"), (0x180199E08, "evt_180199e08")): f = func(va) print("\n########## %s addr %#x in %s @%#x ##########" % (tag, va, f.getName() if f else "?", int(f.getEntryPoint().getOffset()) if f else 0)) s = dec(va) print("len=%d" % len(s)) print(s) open(OUT + "/d1_%s.txt" % tag, "w").write(s) print("\n########## callers of the getter 0x18011c1f0 ##########") for (fr, ty, fn, en) in xrefs_to(0x18011C1F0): print(" %#x %-10s %s @%#x" % (fr, ty, fn, en)) print("\nDONE q_pack_inv_10") except Exception: traceback.print_exc()