#!/usr/bin/env python3 """Read the FutDataManagerImpl UI gate bytes out of the LIVE FIFA 17 client. Why this exists: on 2026-08-05 the /settings gate plan concluded that IS_FRIENDLY_SEASON_ENABLED and IS_DRAFT_MODE_ENABLED had never been set true by anything. Measured against the running client, both are 1, and have been all along. The applier FUN_18011dc50 runs whether or not the configs array has content, and the settings struct it is handed defaults these fields to 1. "Nothing populates the array" is not "nothing writes the byte". Read-only. Opens /proc//mem O_RDONLY and preads. Nothing here can write. Nothing is assumed: * the pid is resolved by exact /proc/*/comm match, never hardcoded * the CardsDLL base is read from /proc//maps, never cached across launches (Wine copies the sections into anonymous memory, so only the 4 KiB PE header is file-backed and `grep CardsDLL maps` returns exactly ONE line, which is easy to misread as "barely mapped") * the slide is PROVEN against the FNV atom-hash prologue at 0x180180d00, read from the on-disk PE, before any other address is trusted * each gate byte displacement is DECODED from its accessor stub (0f b6 81 , movzx eax, byte [rcx+disp32]) rather than taken from a table Requires the client to have reached Ultimate Team, since CardsDLL loads only then. Usage: python3 gate_byte_probe.py """ import os, struct, sys pid=None for d in os.listdir('/proc'): if d.isdigit(): try: if open('/proc/%s/comm'%d).read().strip()=='FIFA17.exe': pid=int(d); break except Exception: pass assert pid, "not running" print("pid", pid) base=None for ln in open('/proc/%d/maps'%pid): if 'CardsDLL' in ln: base=int(ln.split('-')[0],16); print("cardsdll map line:", ln.strip()) assert base slide = base - 0x180000000 print("base %#x slide %#x" % (base, slide)) fd=os.open('/proc/%d/mem'%pid, os.O_RDONLY) def rd(va,n): return os.pread(fd, n, va) # control: FNV prologue, bytes taken from the on-disk PE pe=open('/mnt/games/FIFA 17/CardsDLL_Win64_retail.dll','rb').read() # .text rva 0x1000 rawptr 0x400 def f(va): return va-0x180000000-0x1000+0x400 ctl_disk=pe[f(0x180180d00):f(0x180180d00)+32] ctl_live=rd(0x180180d00+slide,32) print("CONTROL FNV", "MATCH" if ctl_disk==ctl_live else "MISMATCH", ctl_live.hex()) # model singleton dat=0x1802e6398+slide obj=struct.unpack('", hex(obj)) vt=struct.unpack(' %#x stub=%s disp=%s value=%s" % (off, slot-slide, stub.hex(), hex(disp) if disp else None, val)) # unopenedPacks total print("model+0x20950 =", struct.unpack('