Emulates FIFA 17's full online + Ultimate Team stack against an offline,
clean-room backend (no EA servers). Proven end-to-end 2026-08-01:
Origin login -> Blaze login -> device-trust -> the FUT hub.
Package:
- tools/openfut-fut.sh one-command orchestrator (start/stop/status/restart)
- tools/root_arm.sh idempotent host arm (sysctls, DNAT, /etc/hosts easw)
- tools/{lsx_responder_v2,blaze_responder_v3b,roster_server,utas_server,autopatch}.py
the 5 servers (Origin LSX :4216, Blaze :42127/42130/42131, roster :8081,
FUT/UTAS :8099) + heat2.py (Fire2/Heat2 TDF codec)
- FUT-RUNBOOK.md runbook + gate-ladder troubleshooting
- docs/, tools/login_dump/*.md the reverse-engineering write-ups
All findings are clean-room, from binaries we own; nothing from any leak.
The wire protocol maps 1:1 to FIFA 23.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PN5bmpDVQR1aXgefyWAt7o
4.5 KiB
Agent brief — reverse the FIFA17 first-party auth-request ENQUEUE path (clean-room)
Clean-room rule (HARD)
Derive everything ONLY from the decrypted .bin/.asm dumps in THIS directory (dumped
from our own running FIFA17.exe via /proc/PID/mem) + arithmetic. NEVER use leaked EA source.
The goal
FIFA never completes online login. Root cause, localized to instruction level:
FifaOnline::FirstPartyAuthTokenRetriever::DoTick @ 0x146f199c0 runs every frame:
146f199cd lea rbx,[rcx+0x8] ; rbx = &authRequestQueueHead (rcx = the retriever object)
146f199e0 mov rsi,[rbx] ; rsi = queue head node ptr (ALWAYS 0 live)
146f199e3 test rsi,rsi
146f199e6 je 0x146f19ae1 ; head==NULL -> exit, does nothing
146f199f6 call 0x1470da6d0 ; else process the node
The queue head (retriever+0x8) is null forever -> no GetAuthCode -> no token -> no Blaze
login -> "Unable to retrieve account information". Live-confirmed: entering FUT / Online
Seasons NEVER enqueues a node (the slot stays 0). We can WRITE FIFA memory (ptrace_scope=0).
DELIVERABLE: everything needed to FORGE a FirstPartyAuthCodeFutureImpl node, write it into
FIFA's memory, and set retriever+0x8 to point at it — so DoTick processes it and fires
GetAuthCode over LSX. Plus: identify what SHOULD enqueue it (and why FIFA skips that), as a
cross-check.
Live object layout (this instance; pointers are per-run, offsets are stable)
- retriever object @
*[0x1448a3b20] + 0x4e98= live0x43dc8d08.+0x00= vtable ptr0x1438f5d50+0x08= auth-request queue HEAD (the null slot DoTick reads) [live addr 0x43dc8d10]+0x10=0x0[live 0x43dc8d18]
- retriever vtable @
0x1438f5d50, first 9 slots are methods (rest is .rdata RTTI/strings):[0]0x146f02960 [1]0x147e8f160 [2]0x147e1c480 [3]0x146f028d0 [4]<data> [5]0x1471a0630[6]0x1466cc0d0 [7]0x147104dc0 [8]0x146f009e8then[28]0x146ceaeb0 [29]0x146f60060[30]0x146f5f8b0 [31]0x146f3eea0. RTTI strings embedded there decode to:"FifaOnline::FirstPartyAuthCodeFutureImpl","FifaOnline::FirstPartyAuthTokenRetriever::DoTick","[%s] Invalid authcode","[%s] Origin Error(%d)".
Dumps available here (objdump Intel, VMA==runtime VA; grep/Read these)
dotick_full_146f199c0.bin.asmDoTick full (queue iteration + node field reads + call 0x1470da6d0)origin_getdefaultuser_1470da6d0.bin.asmthe node PROCESSOR called by DoTick (0x1470da6d0)origin_getdefaultpersona_1470da680.bin.asmauthcode_sync_full_1470db3c0.bin.asmOriginRequestAuthCodeSync (0x1470db3c0) — builds/sends LSX GetAuthCodeorigin_authcode_req_1470da600.bin.asmvt00_*.asm…vt08_*.asm,vt28_*…vt31_*the retriever's vtable methods (one ENQUEUES; find it)dispatch_case2_*,event_matcher_*,login_parser_*(Origin LSX event path, context)auth_block_43dc8d08.bin(raw retriever region snapshot),manifest.txt
Method (these are decrypted normal x86-64; objdump works directly)
objdump -D -b binary -m i386:x86-64 -M intel --adjust-vma=0xVA file.bin for any window.
To dump MORE decrypted code from the LIVE game (pid in manifest.txt / pgrep -x FIFA17.exe),
read /proc/PID/mem (ptrace_scope=0): f.seek(va); f.read(n) then objdump with --adjust-vma.
Follow call targets you need (e.g. what 0x1470da6d0 calls, the ctor of FirstPartyAuthCodeFutureImpl).
Every claim needs a VA / byte / disasm excerpt.
Key questions to answer
- Node struct (
FirstPartyAuthCodeFutureImpl): exact field layout DoTick + 0x1470da6d0 read — thenextpointer (linked-list link), vtable, state/status field, ClientId/Scope inputs, result/callback fields. Enough to FORGE a minimal valid node. - DoTick processing: after
rsi=head, what does it read from[rsi+...]? Does it walk a linked list (nextat some offset)? What does 0x1470da6d0 do with the node + the out-params at[rsp+0x58]/[rsp+0x60](r9/r8)? Where does it call OriginRequestAuthCodeSync / send GetAuthCode? - Enqueue method: which retriever vtable slot (vt00-08/28-31) appends a node to
+0x8? What is its signature? Who calls it (the online-login-initiate path) and why is it skipped? - OriginRequestAuthCodeSync (0x1470db3c0): its signature + what it needs to send the LSX
<GetAuthCode ClientId Scope>request. Could we call it DIRECTLY (gdbcall) as a shortcut? - The forge-and-trigger plan: exact bytes to write, where to allocate the node, what to set
retriever+0x8to, and what we expect to observe (GetAuthCode on /tmp/lsx.log). Flag crash risks.