docs: recover GetAuthCode request format; localize gate to EASFC job-enqueue poll
Traced the far end of the online gate: FIFA's GetAuthCodeT::Serialize (+0x278d2c0) yields the exact LSX request it would send to start the Nucleus->Blaze chain -- <GetAuthCode UserId ClientId Scope AppendAuthSource/>. It is wrapped by a GetAuthCodeJob in the EASFC online-job module. The wall is not the LSX wire or event delivery (events parse fine) but that FIFA's EASFC controller never enqueues the job -- it polls cached online state and our single isOnline flag doesn't satisfy the combined condition. Closes the is-it-the-events question (no); next artifact is the controller poll guard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -761,9 +761,90 @@ path alone flips the game-side online state machine — the real gate is in FIFA
|
|||||||
online orchestrator, reachable only by probing the runtime virtual listener or a
|
online orchestrator, reachable only by probing the runtime virtual listener or a
|
||||||
deeper RE of that state machine.
|
deeper RE of that state machine.
|
||||||
|
|
||||||
|
### Live listener captured — the event callback is a NO-OP (2026-07-02)
|
||||||
|
|
||||||
|
Added a behavior-preserving mid-function detour (probe.rs `openfut_listener_stub`,
|
||||||
|
patch at FIFA23.exe+0x274d4d7) to capture the runtime target of the OnlineStatusEvent
|
||||||
|
dispatch (`call [rax+0x28]`). Result:
|
||||||
|
|
||||||
|
```
|
||||||
|
PROBE OnlineStatus.listener: vtable=0x1480b9ac0 (rva 0x80b9ac0) fn=0x142751060 (rva 0x2751060)
|
||||||
|
```
|
||||||
|
|
||||||
|
`FIFA23.exe+0x2751060` is `ret 0x0` — a **no-op**, one of a table of identical `ret 0`
|
||||||
|
stubs (i.e. the default/empty virtual slot; this object does not override the
|
||||||
|
online-status notification). So the immediate event callback does nothing.
|
||||||
|
|
||||||
|
**Reframes the approach.** `OnlineStatusEventT::HandleMessage` does two things: it
|
||||||
|
stores the parsed bool into a map (state), then calls this (no-op) notify. So our push
|
||||||
|
updates FIFA's *stored* online state but triggers no active reaction — there is no
|
||||||
|
callback to kick off the auth/Blaze chain. The transition must be driven by FIFA
|
||||||
|
**polling** that stored state (consistent with the observed GetProfile /
|
||||||
|
GetInternetConnectedState polling), gated on some combined condition our single
|
||||||
|
online flag doesn't satisfy. Event-pushing alone cannot trigger it; the next dig is
|
||||||
|
the state reader / poll gate (who reads the map HandleMessage writes, and what else it
|
||||||
|
requires), which is deeper FIFA-internal RE.
|
||||||
|
|
||||||
|
The probe tooling now cleanly captures live virtual-dispatch targets (alignment-safe
|
||||||
|
mid-function detour) — reusable for the next layer.
|
||||||
|
|
||||||
### Next gate: Blaze/online (M2)
|
### Next gate: Blaze/online (M2)
|
||||||
|
|
||||||
"connecting to EA servers" is the Blaze layer. The hook log shows FIFA has made **no**
|
"connecting to EA servers" is the Blaze layer. The hook log shows FIFA has made **no**
|
||||||
Blaze connect yet (nothing on 443/10041/42127) while spinning, so it is stalled at
|
Blaze connect yet (nothing on 443/10041/42127) while spinning, so it is stalled at
|
||||||
pre-auth. Per the architecture, Blaze rides ProtoSSL in-process (a different transport
|
pre-auth. Per the architecture, Blaze rides ProtoSSL in-process (a different transport
|
||||||
than LSX), so serving it is separate, larger work — the M2 effort, now actually reached.
|
than LSX), so serving it is separate, larger work — the M2 effort, now actually reached.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GetAuthCode request format recovered — the gate is job-enqueue, not event-push (2026-07-02)
|
||||||
|
|
||||||
|
Continuing past the "live listener is a NO-OP" finding, I traced the *other end* of
|
||||||
|
the gate: the LSX request FIFA must send to start the Nucleus→Blaze chain, and what
|
||||||
|
gates it. Static RE of FIFA23.exe (clean-room; the client's own serializers are the
|
||||||
|
oracle).
|
||||||
|
|
||||||
|
**The request FIFA would send (exact, from its serializer at FIFA23.exe+0x278d2c0):**
|
||||||
|
|
||||||
|
```
|
||||||
|
<GetAuthCode UserId="<int>" ClientId="<str>" Scope="<str>" AppendAuthSource="true|false"/>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Serializer `GetAuthCodeT::Serialize` @ **FIFA23.exe+0x278d2c0**. Element string
|
||||||
|
`GetAuthCode` @ .rdata 0x1480c27d0 (its *only* xref — this is the sole builder).
|
||||||
|
- Field layout in the request struct: `UserId=[rbx+0x00]`, `ClientId=[rbx+0x08]`
|
||||||
|
(string), `Scope=[rbx+0x28]` (string), `AppendAuthSource=[rbx+0x48]` (bool).
|
||||||
|
- Attribute-name strings: `UserId` 0x147ea7bc8, `ClientId` 0x1480c2c98,
|
||||||
|
`Scope` 0x147c79514, `AppendAuthSource` 0x1480c2ca8.
|
||||||
|
- This is rung 1 of M2's auth chain: FIFA asks the SDK (== us, over LSX) for a Nucleus
|
||||||
|
auth code; it then exchanges that code at accounts.ea.com → token → gosredirector →
|
||||||
|
Blaze. We now know the exact request to answer once we can make FIFA send it.
|
||||||
|
|
||||||
|
**Who sends it — and the actual gate.** The request is wrapped by a **`GetAuthCodeJob`**
|
||||||
|
inside FIFA's EASFC online-job module (a large block ~FIFA23.exe+0x51b0000..0x528xxxx;
|
||||||
|
job/response telemetry tags `GetAuthCodeJob` @ 0x1484630d0, `GetAuthCodeJobResponse` @
|
||||||
|
0x148455b98). The job's completion/response handler is at **FIFA23.exe+0x51b66c0** (sets
|
||||||
|
its done-flag `[r15+8]=1`, logs via those tags). The serializer is invoked polymorphically
|
||||||
|
from the LSX client when the job runs — it is **not** called directly, so there is no
|
||||||
|
static call-xref from the trigger; the job is *enqueued* by the EASFC online controller's
|
||||||
|
state machine.
|
||||||
|
|
||||||
|
**Conclusion (the gate, precisely stated).** The wall is **not** on the LSX wire and
|
||||||
|
**not** in event delivery (our OnlineStatus/Login events parse fine; cf. the no-op-listener
|
||||||
|
finding above). The wall is that FIFA's **EASFC online controller never enqueues
|
||||||
|
`GetAuthCodeJob`**. That controller decides "am I online enough to authenticate?" by
|
||||||
|
*polling* its cached online state (the map `OnlineStatusEventT::HandleMessage` writes),
|
||||||
|
and our single `isOnline=true` flag does not satisfy its combined condition. So:
|
||||||
|
|
||||||
|
- Event-push alone cannot cross it (confirmed twice now, from both ends).
|
||||||
|
- The true next artifact is the **EASFC controller's online-readiness poll** — the guard,
|
||||||
|
in that 0x51b0000..0x528xxxx module, that must pass before `GetAuthCodeJob` is enqueued.
|
||||||
|
That is a large state-machine RE (hundreds of KB of EASFC job code), i.e. the genuine
|
||||||
|
multi-week M2 frontier the status review priced.
|
||||||
|
|
||||||
|
**Net for this session:** recovered the exact `GetAuthCode` request format (so the round
|
||||||
|
trip is ready when we cross the gate) and localized the gate to a specific FIFA module and
|
||||||
|
mechanism (EASFC job-enqueue poll, not LSX/events). This closes the "is it the events?"
|
||||||
|
question — it is not. The remaining work is FIFA-internal EASFC state-machine RE, which
|
||||||
|
sits directly against the [[project_direction_pivot]] (FLE career mode is the stated
|
||||||
|
primary plan) as a cost/priority decision, not a technical unknown on the LSX side.
|
||||||
|
|||||||
Reference in New Issue
Block a user