LSX: push OnlineStatusEvent + Login to drive FIFA online (M2 probe)
Add an unsolicited event-push path to the LSX server: after the session establishes, re-push (every 2s) a Login then OnlineStatusEvent, encrypted with the live session seed and null-terminated like any session frame. Formats RE'd from FIFA23.exe's OriginSDK deserializers (authoritative): <Login UserIndex="0" IsLoggedIn="true" LoginReasonCode="0"/> (LoginT, +0x287a30) <OnlineStatusEvent isOnline="true"/> (OnlineStatusEventT, +0x28a4d0) Value encoding is the true/false string literal (FIFA's bool parser at FIFA23.exe+0x28fb50 compares to "false"); isOnline="1" is parsed as not-online. Result (verified with in-process probes): FIFA parses both events every cycle and returns success, and stops its impatient GetProfile polling / sets INGAME presence — the first time FIFA has been driven "online" at the EbisuSDK level (anadius, being offline DRM, never does this). But FIFA does not proceed to the GetAuthCode→Nucleus →Blaze chain; the gate is its game-side event consumer (virtual dispatch at FIFA23.exe+0x274d4e2), not delivery. Full trail in docs/connection-gate-findings.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -592,6 +592,175 @@ from it during online-init. With the service absent, the handle was null → the
|
||||
registry Name). This is the first change that targets the *actual* crash address, so
|
||||
it is the real test of the loading-screen gate.
|
||||
|
||||
### M2 unblock lever RECOVERED: the ONLINE_STATUS_EVENT push format (2026-07-02)
|
||||
|
||||
With the LSX gate cleared, FIFA sits at "connecting to EA Servers", polling GetProfile
|
||||
over LSX. Per the M1/M2 findings this is the async-push wall: FIFA calls GoOnline
|
||||
(handled in-process by anadius/EbisuSDK), gets success, then **waits for an
|
||||
`ONLINE_STATUS_EVENT` push on the LSX socket that never arrives.** Earlier attempts
|
||||
couldn't send it — it was unclear the bridge even owned the LSX socket (anadius
|
||||
intercepted in-process). **That blocker is now gone: our bridge provably owns FIFA's
|
||||
LSX socket** (full session runs on :3217), so we can finally push the event.
|
||||
|
||||
RE recovered the exact format the client parses (authoritative — from FIFA23.exe's
|
||||
own OriginSDK deserializer, not a guess):
|
||||
|
||||
- **Event wrapper** (from anadius64.dll's IGOEvent template):
|
||||
`<LSX><Event sender="EbisuSDK"><…/></Event></LSX>`
|
||||
- **Element** `OnlineStatusEvent` — confirmed via FIFA23.exe's retained RTTI symbol
|
||||
`Origin::EventHandler<struct lsx::OnlineStatusEventT,bool>::HandleMessage`
|
||||
(source path `OriginSDK/10.6.2.19-fb-fifagame/src/impl/OriginEventClasses`) and the
|
||||
event-name dispatch table. Handler parser at FIFA23.exe+0x274d4ae.
|
||||
- **Attribute** `isOnline` (a single bool) — recovered from the typed deserializer at
|
||||
FIFA23.exe+0x28a4d0: it inits the output byte to 0 (offline), builds an `lsx:`
|
||||
namespace prefix, reads the `isOnline` attribute, and string→bool converts it.
|
||||
|
||||
Best-effort push (value format `1` vs `true` is `TODO/CONFIRM` against the client —
|
||||
OriginSDK bool attributes elsewhere use `true`/`false`):
|
||||
|
||||
```xml
|
||||
<LSX><Event sender="EbisuSDK"><OnlineStatusEvent isOnline="1"/></Event></LSX>
|
||||
```
|
||||
|
||||
**Next implementation step:** give the bridge LSX server an async, unsolicited-push
|
||||
path — encrypt this event with the live session seed and write it on the open socket
|
||||
after the session establishes (or after FIFA's GoOnline settles). Success signal: FIFA
|
||||
stops polling and **dials the Blaze redirector** (gosredirector → :42127 via the hook),
|
||||
which yields the first Fire2 frame and moves us into M3/M4 (fifa-blaze).
|
||||
|
||||
### RESULT: OnlineStatusEvent push drives FIFA online — a first — but the auth→Blaze chain is the next wall (2026-07-02)
|
||||
|
||||
Implemented an unsolicited `OnlineStatusEvent` push in the bridge LSX server
|
||||
(`select!` loop, encrypted with the session seed, re-pushed every 2s). Value
|
||||
`isOnline="true"` (FIFA's bool parser at FIFA23.exe+0x28fb50 string-compares to
|
||||
`false`; `isOnline="1"` was delivered but parsed as not-online — pinned the encoding).
|
||||
|
||||
**FIFA reacted — the event format is correct and effective:**
|
||||
- Rapid GetProfile polling (~0.5s) stopped the instant the pushes began (13s gap).
|
||||
- FIFA set `SetPresence … Presence="INGAME"` — an *online* action.
|
||||
- Then it went **silent on LSX** (idle, connection alive, no crash).
|
||||
|
||||
This is the first time FIFA has been driven "online" at the EbisuSDK/LSX level —
|
||||
**anadius never does this** (it is offline DRM and deliberately keeps FIFA offline),
|
||||
so this path is genuinely uncharted, not a regression from a known-good baseline.
|
||||
|
||||
**But FIFA does NOT proceed to Blaze.** After going online it:
|
||||
- sent **no** `GetAuthCode` (an LSX request the bridge already answers) — so it never
|
||||
started the Nucleus-token exchange;
|
||||
- resolved **no** hostname (`hooked_getaddrinfo` logs every call; the hook log has
|
||||
none) — no gosredirector, no accounts.ea.com;
|
||||
- opened **no** socket beyond LSX (:3216).
|
||||
|
||||
So a single connectivity event ≠ full online login. RE of FIFA23.exe confirms the
|
||||
remaining chain and its anchors: `GetAuthCode` (12×) → `NucleusAccessToken` /
|
||||
`access_token` / `Bearer` / `Authorization` (redirector header) → `gosredirector`
|
||||
(4×) / `BlazeHub` (3×) → Blaze auth. `OnlineStatusEventT::HandleMessage`
|
||||
(FIFA23.exe+0x274d4ae) only builds the typed event and dispatches it via the SDK
|
||||
callback; the game-side listener that would kick off the auth chain needs more than
|
||||
the connectivity flag (candidate: a login/authenticated-online event or an in-process
|
||||
EbisuSDK login step that our LSX-only redirect doesn't cover).
|
||||
|
||||
**Strategic note:** this is the M2→M6 research frontier the 2026-06-30 status review
|
||||
priced at months of expert RE, now empirically confirmed. It sits against the
|
||||
2026-06-30 direction pivot, which made the app-centric FLE/career-mode path the
|
||||
primary plan over full Blaze-backend RE. Decision point before sinking weeks into the
|
||||
Nucleus/Blaze stack.
|
||||
|
||||
### Trigger hunt: the missing link is the `Login` event (OriginLoginT) (2026-07-02)
|
||||
|
||||
Traced why FIFA stalls after going online. The full post-online chain and its
|
||||
FIFA23.exe anchors:
|
||||
|
||||
```
|
||||
OnlineStatusEvent(isOnline=true) ✓ delivered, FIFA set INGAME presence
|
||||
│ [MISSING game-side trigger]
|
||||
GetAuthCode (LSX request we answer) ── never sent
|
||||
│
|
||||
Nucleus token exchange (accounts.ea.com HTTPS, Bearer/Authorization) ── no DNS
|
||||
│
|
||||
spring18.gosredirector.ea.com (HTTPS redirector: Authorization + serviceName,
|
||||
env-selected by ENVIRONMENT="production"; headers X-BLAZE-ERRORCODE)
|
||||
│
|
||||
Blaze server (BlazeHub::LoginManagerImpl, Fire2) ── never reached
|
||||
```
|
||||
|
||||
Login lives inside Blaze (`BlazeHub::mLoginManagers`), which needs a Nucleus token
|
||||
first, which needs `GetAuthCode`, which FIFA never issues. So the block is upstream:
|
||||
the game-side reaction to online doesn't start the auth chain.
|
||||
|
||||
**Likely cause — no authenticated session.** FIFA's Origin event set (from retained
|
||||
RTTI) includes `Origin::EventHandler<struct lsx::LoginT, struct OriginLoginT>` — a
|
||||
`Login` event carrying a full `OriginLoginT` struct (identity/session/token), distinct
|
||||
from `OnlineStatusEvent`'s single bool. Our push set *connectivity* (presence went
|
||||
INGAME) but not an authenticated *session*. anadius never pushes `Login` (offline DRM),
|
||||
so FIFA has a persona (from GetProfile) but no online session token → nothing to drive
|
||||
`GetAuthCode`.
|
||||
|
||||
**Next experiment:** RE the `LoginT` deserializer (element `Login`, payload
|
||||
`OriginLoginT`) the same way as OnlineStatusEvent, synthesize a `<Login>` event push
|
||||
with a fabricated session, and relaunch. Success signal: FIFA issues `GetAuthCode`
|
||||
over LSX and/or resolves `spring18.gosredirector.ea.com` (both logged) — the first
|
||||
move into the Nucleus/Blaze stack.
|
||||
|
||||
### Login event pushed — FIFA still won't start the auth chain (2026-07-02)
|
||||
|
||||
RE'd the `Login` event from FIFA23.exe's `LoginT` deserializer (0x142787a30): fields
|
||||
`UserIndex` (int), `IsLoggedIn` (bool, same true/false parser as isOnline),
|
||||
`LoginReasonCode` (int). Pushed `<Login UserIndex="0" IsLoggedIn="true"
|
||||
LoginReasonCode="0"/>` before OnlineStatusEvent each cycle.
|
||||
|
||||
Result: **no change.** FIFA reacts to connectivity (presence INGAME, polling backs
|
||||
off) but issues no `GetAuthCode`, resolves no host (`getaddrinfo` count 0), dials no
|
||||
Blaze. So Login + OnlineStatus (connectivity + authenticated flags) are **not**
|
||||
sufficient to trigger the game-side auth chain.
|
||||
|
||||
**Boundary reached for black-box LSX emulation.** We can drive every LSX-wire signal
|
||||
FIFA reads, and FIFA visibly reacts, but the decision to start GetAuthCode→Nucleus→
|
||||
Blaze lives in FIFA's game-side online orchestrator, whose gating state is invisible
|
||||
from the LSX wire (it also makes in-process EbisuSDK calls that go to anadius, not our
|
||||
socket — we can't see those). Guessing more LSX events is low-yield from here.
|
||||
|
||||
To progress, the next step must convert guessing into observation — **instrument
|
||||
FIFA's in-process online flow** via the hook DLL: detour the EbisuSDK/game functions
|
||||
around `GetAuthCode`, `GoOnline` (anadius64.dll+0x2BB90), and the OnlineStatusEvent
|
||||
consumer, and log what FIFA does after our events (whether it calls GetAuthCode
|
||||
in-process, what it checks, where it returns early). That reveals the exact gate.
|
||||
Alternatively this is the wall the 2026-06-30 direction pivot anticipated — the
|
||||
app-centric FLE/career path avoids the online-backend entirely.
|
||||
|
||||
Bank: LSX gate cleared; FIFA driven "online" at the EbisuSDK connectivity/login level
|
||||
for the first time (anadius never does); OnlineStatusEvent + Login formats recovered
|
||||
and confirmed effective at the event level.
|
||||
|
||||
### In-process instrumentation results (2026-07-02)
|
||||
|
||||
Built a `probe` feature into openfut-hook (unhook/rehook logging detours, like
|
||||
connect_hook) on four online-flow functions. Deployed + ran with the event push
|
||||
active. Results (C:\openfut_hook.log):
|
||||
|
||||
- **Our events reach FIFA's code and parse successfully.** `OnlineStatus.deser`
|
||||
(FIFA23.exe+0x28a4d0) and `Login.deser` (+0x287a30) each fired 44× (once per 2s
|
||||
re-push) and returned success (0x1 / valid ptr). The push works at the deepest
|
||||
level — not a delivery problem.
|
||||
- **`GoOnline` (anadius64.dll+0x2bb90) never fires.** The 2026-06-30 review saw FIFA
|
||||
calling GoOnline and *retrying every ~7s*; with our bridge + events FIFA is not in
|
||||
that retry loop at all. Our events moved it out of the retry state — but it does not
|
||||
advance.
|
||||
- **`GetInternetConnectedState` (anadius64.dll+0x27790) never fires** — FIFA asks it
|
||||
over LSX (to our bridge) instead; anadius is fully bypassed for LSX.
|
||||
|
||||
**Gate localized to the game-side event consumer.** After the deserializer,
|
||||
`OnlineStatusEventT::HandleMessage` delivers the value via a virtual call
|
||||
(`call [rax+0x28]`, FIFA23.exe+0x274d4e2) to a polymorphic game listener. FIFA parses
|
||||
"online + logged in" every cycle but the listener does not act (no GoOnline, no auth,
|
||||
no Blaze). The concrete listener is a runtime vtable target — not statically pinnable.
|
||||
|
||||
Note vs. the old M2 finding: forcing anadius's in-process state flags to online left
|
||||
FIFA *retrying*; pushing our events *stops* the retry but doesn't advance. Neither
|
||||
path alone flips the game-side online state machine — the real gate is in FIFA's own
|
||||
online orchestrator, reachable only by probing the runtime virtual listener or a
|
||||
deeper RE of that state machine.
|
||||
|
||||
### Next gate: Blaze/online (M2)
|
||||
|
||||
"connecting to EA servers" is the Blaze layer. The hook log shows FIFA has made **no**
|
||||
|
||||
Reference in New Issue
Block a user