"""ADVERSARIAL verify of Seasons Findings 2 & 4 + getter offsets.
HYPOTHESIS UNDER ATTACK:
 F2: model+0x5c68 season vector written ONLY by FUN_1801683f0 (/season deser).
 F4: SEASONLIST descriptor @0x1802cb718 and URL 'ut/%s/season' @0x18021e598 have no code xref.
 Getters: vtable+0x898 -> lea rax,[rcx+0x5c68]; vtable+0x588 -> lea rax,[rcx+0x7138].
CONTROL: resolve a KNOWN getter/xref form the same way (disp32 immediate scan) and
 confirm the scanner actually finds multi-hit patterns (not silently zero).
"""
import traceback
try:
    MODEL_VT=0x18021c2a0
    # 1. getter slots
    for slot in (0x898,0x588,0x988,0x990):
        t=qword(MODEL_VT+slot)
        print("vtable +%#x -> %#x %s" % (slot,t,fname(t)))
        print("   dec head:", " | ".join(dec(t).splitlines()[:6]))
    # 2. disp32 immediate scan in .text for 0x5c68 (le 4-byte) and 0x7138
    for off_name,val in (("0x5c68",0x5c68),("0x7138",0x7138),("0x1fd3a",0x1fd3a)):
        pat=val.to_bytes(4,'little')
        hits=find_all(pat, blocks=(".text",))
        print("\ndisp32 scan .text for %s (%s): %d hits" % (off_name, pat.hex(), len(hits)))
        for h in hits[:12]:
            f=func(h); print("   @%#x in %s" % (h, f.getName() if f else '?'))
    # 3. call sites of [reg+0x898] -- scan .text for the modrm/disp32 forms of call [r+0x898]
    #    common encodings: FF 90 98 08 00 00 (call [rax+0x898]); reg varies in modrm middle bits.
    print("\n--- call [reg+0x898] sites (FF /2 disp32 = 98 08 00 00) ---")
    disp=(0x898).to_bytes(4,'little')
    for pat_desc,pat in [("call [rax+d]",b"\xff\x90"+disp),("call [rcx+d]",b"\xff\x91"+disp),
                          ("call [rdx+d]",b"\xff\x92"+disp),("call [rbx+d]",b"\xff\x93"+disp),
                          ("call [rsi+d]",b"\xff\x96"+disp),("call [rdi+d]",b"\xff\x97"+disp),
                          ("call [r8+d]",b"\x41\xff\x90"+disp),("call [r9+d]",b"\x41\xff\x91"+disp),
                          ("call [r10+d]",b"\x41\xff\x92"+disp),("call [r11+d]",b"\x41\xff\x93"+disp)]:
        hits=find_all(pat, blocks=(".text",))
        for h in hits:
            f=func(h); print("   %s @%#x in %s" % (pat_desc,h,f.getName() if f else '?'))
    # 4. Finding 4: descriptor + url xrefs
    print("\n--- F4: SEASONLIST descriptor / url xrefs ---")
    print("xrefs_to(0x1802cb718):", xrefs_to(0x1802cb718))
    print("xrefs_to(0x18021e598) url ut/%s/season:", xrefs_to(0x18021e598))
    print("string @0x18021e598:", repr(rd_str(0x18021e598)))
    # SEASONLIST literal locate
    sl=find_all(b"SEASONLIST\x00")
    print("SEASONLIST literal at:", [hex(x) for x in sl])
    for a in sl:
        print("  xrefs_to(%#x):"%a, xrefs_to(a))
    # url literal locate
    us=find_all(b"ut/%s/season\x00")
    print("'ut/%s/season' literal at:", [hex(x) for x in us])
    for a in us:
        print("  xrefs_to(%#x):"%a, xrefs_to(a))
except Exception:
    traceback.print_exc()
