#!/usr/bin/env python3 """Force the FIFA 17 FUT store OPEN by patching CardsDLL's online-readiness gate. The "store is not available" screen is gated by FIFA's online-mode manager (FUT::CompetitionManager). Three CardsDLL methods report store-enabled and only return true once that manager reaches the online "service ready" state -- an online/Blaze wall we can't reach offline. This pokes them to return true. Reversible: originals are saved to /tmp/orig_.bin; `restore` puts them back; a FIFA restart also clears the patch (live-memory only, per session). Needs ptrace_scope=0 (tools/root_arm.sh) and FIFA running. Run as YOUR action: !python3 tools/store_enable_poke.py # patch (open the store) !python3 tools/store_enable_poke.py restore # undo Static gate methods (CardsDLL image base 0x180000000), patched to `mov eax,1; ret`: 0x1800f7fb0 IS_EASTORE_SERVICE_READY (mgr[0x6d4]==0x1fbd0) 0x1800fb850 IS_STORE_ENABLED (online-mode state stack non-empty) 0x180100500 IS_COIN_PURCHASABLE (commerce config) """ import sys, glob, os IMG_BASE = 0x180000000 GATES = { 0x1800f7fb0: "IS_EASTORE_SERVICE_READY", 0x1800fb850: "IS_STORE_ENABLED", 0x180100500: "IS_COIN_PURCHASABLE", } RET_TRUE = bytes.fromhex("b801000000c3") # mov eax,1 ; ret DLL_MATCH = "CardsDLL" def find_pid(): for d in glob.glob('/proc/[0-9]*'): try: if open(d + '/comm').read().strip() == 'FIFA17.exe': return int(d.split('/')[-1]) except Exception: pass raise SystemExit("FIFA17.exe not running") def cardsdll_base(pid): for line in open(f'/proc/{pid}/maps'): if DLL_MATCH in line: return int(line.split('-')[0], 16) # lowest mapping = module base raise SystemExit("CardsDLL not mapped in FIFA process") def main(): restore = len(sys.argv) > 1 and sys.argv[1] == "restore" pid = find_pid() base = cardsdll_base(pid) print(f"FIFA pid={pid} CardsDLL base={base:#x} ({'RESTORE' if restore else 'PATCH'})") mem = f'/proc/{pid}/mem' for va, name in GATES.items(): live = base + (va - IMG_BASE) origf = f'/tmp/orig_{live:x}.bin' if restore: if not os.path.exists(origf): print(f" {name}: no saved original, skip"); continue data = open(origf, 'rb').read() else: with open(mem, 'rb') as f: f.seek(live); orig = f.read(len(RET_TRUE)) open(origf, 'wb').write(orig) data = RET_TRUE with open(mem, 'r+b') as f: f.seek(live); f.write(data) f.seek(live); chk = f.read(len(data)) print(f" {name:26s} @ {live:#x} -> {chk.hex()}") print("Done." + ("" if restore else " Now open the FUT Store in-game.")) if __name__ == "__main__": main()