Files
OpenFUT/fifa17-recon/tools/ghidra_queries/q_md_draft_5.py
T

38 lines
1.7 KiB
Python

"""DIMENSION 4 q5: map model vtable slots +0x2b0..+0x320 to their accessor
displacements, so slot +0x2d0 (the offline-draft-specific gate in FUN_1800b2680)
and slot +0x320 (cVar9) can be measured live.
Model vtable static = 0x18021c2a0 (from ground truth / card doc). For each slot read
the target function's first bytes; if it is the accessor stub 0f b6 81 <disp32> c3
(movzx eax,byte [rcx+disp]; ret) decode disp.
Control: slot +0x270 must decode to disp 0x1fd2e (IS_TRADING), slot +0x2c8 to 0x1fd3d
(IS_DRAFT_MODE_ENABLED) -- both established in the card-subsystem doc.
"""
import traceback
try:
VT = 0x18021c2a0
names = {0x270:"IS_TRADING(+0x1fd2e)", 0x280:"IS_STORE", 0x2b0:"FRIENDLY_SEASON(+0x1fd3a)",
0x2b8:"TOURNAMENT_QUIT(+0x1fd3b)", 0x2c0:"PROCESSING(+0x1fd3c)",
0x2c8:"DRAFT_MODE(+0x1fd3d)", 0x2d0:"?offline-draft gate?",
0x2d8:"STORY_MODE_REWARD", 0x2e0:"packAnim(+0x1fd45)",
0x2f0:"RETURNING_USER", 0x320:"cVar9(FUN_1800b2680)"}
for slot in range(0x2a0, 0x330, 8):
tgt = qword(VT + slot)
b = read_bytes(tgt, 8)
disp = None
if b[:3] == b"\x0f\xb6\x81": # movzx eax, byte [rcx+disp32]
import struct
disp = struct.unpack("<i", b[3:7])[0]
note = names.get(slot, "")
print("slot +%#05x -> %#012x stub=%s disp=%s %s" %
(slot, tgt, b.hex(), hex(disp) if disp is not None else "(not a byte-accessor)", note))
if disp is None:
# decompile non-trivial accessors (offline draft gate / cVar9 may compute)
if slot in (0x2d0, 0x320):
print(" --- dec slot +%#x target ---" % slot)
print(dec(tgt))
except Exception:
traceback.print_exc()
print("QUERY_DONE")