Files
OpenFUT-Bridge/docs/HANDOFF-lsx-2026-07-02.md
T
funman300 0138a39f3e LSX gate: FIFA reaches "connecting to EA Servers" via bridge
Implement the LSX (EA App bootstrap, TCP :3216→:3217) server in the bridge
and clear the loading-screen crash gate. FIFA 23 now completes the full LSX
handshake + session against OpenFUT and advances to the online/Blaze phase
("<persona> is connecting to the EA Servers…") — verified live, not a cached
session (the displayed persona "fun" comes from our GetProfile).

Root cause of the invariant loading-screen crash: get_config() omitted the
PROGRESSIVE_INSTALLATION and PROGRESSIVE_INSTALLATION_EVENT services (Name="PI").
FIFA builds its service registry from GetConfig and resolves that handle during
online-init; the missing service left a null handle it dereferenced at
FIFA23.exe+0x133dfc5 (mov rax,[r13+0x18], r13=NULL) ~2s after LSX — identical
across every prior run. Found via FIFA's own CrashReport_*.json (stable RIP) +
diffing anadius64.dll's service-registration table against ours.

Also in this change:
- process_frame(): handle FIFA's pipelined (batched) LSX messages per read,
  eliminating the ~15s handshake hang.
- Real anadius values (RE'd from anadius64.dll + anadius.cfg): PersonaId/UserId/
  persona, locale list, GetGameInfo fixed `GameInfo="<value>"` attribute,
  GetAllGameInfo 14-attr schema, GetSetting `Setting=` attribute.
- IsProgressiveInstallationAvailable served from sender="PI".
- docs/connection-gate-findings.md: full RE trail; relocate stale openfut-hook
  copy under docs/ (canonical hook lives in openfut-launcher).

Next gate: Blaze/online (M2), ridden over ProtoSSL in-process.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 15:37:33 -07:00

6.2 KiB

Handoff — LSX handshake complete end-to-end

Date: 2026-07-02 Scope of the session: openfut-bridge (the delivery test) that expanded into openfut-launcher/openfut-hook (the fix). Nothing was committed — everything below is uncommitted working-tree state.

Read docs/connection-gate-findings.md (bottom two sections) for the full technical narrative. This file is the short "where we are / what to do next" version.


TL;DR

FIFA 23 now completes the LSX handshake and holds a sustained encrypted session against our own bridge, live — the first EA-side step our code services end-to-end. Three changes made it work:

  1. Hook redirect — FIFA's connect(127.0.0.1:3216) is rewritten to :3217 by our hook. The existing in-process offline shim keys on port 3216 specifically, so a different port slips past it and lands on our host bridge (loopback is shared with the Wine/Proton prefix — same netns).
  2. AES key = 000102030405060708090a0b0c0d0e0f. The [0,1,2,…,15] sequence that looked like a placeholder is the actual session key; confirmed by round-tripping against a captured live session.
  3. Session-seed fixcompute_seed() must take the raw ASCII bytes of the first two chars of our response hex, not parse them as a hex pair.

Last live run: FIFA held one ESTAB connection to the bridge and drove 20 EbisuSDK requests with no crash.


Current deployment state (IMPORTANT)

  • The redirect hook is currently deployed as /mnt/games/FIFA 23/version.dll (md5 dab3952809c24122af228a3201b9357b). While this is in place, FIFA routes LSX to our bridge and requires the bridge running on 3217 or LSX will not complete.
  • Backup of the previous hook: /mnt/games/FIFA 23/version.dll.pre-lsx-redirect.bak (md5 fb7a5aae…).
  • To restore the previous behavior for normal offline play:
    cp "/mnt/games/FIFA 23/version.dll.pre-lsx-redirect.bak" "/mnt/games/FIFA 23/version.dll"
    
  • The bridge process from this session may or may not still be running. Check: pgrep -a openfut-bridge / ss -tlnp | grep 3217.

Uncommitted changes (nothing is committed)

openfut-bridge

  • src/lsx.rs:
    • Seed fix in compute_seed() (the load-bearing change).
    • AES-128 hand-roll replaced with the aes crate (+ a FIPS-197 unit test aes128_matches_fips197_and_round_trips).
    • A debug log line dumping raw session ciphertext (used during verification against the capture; harmless to keep, or remove).
  • Cargo.toml / Cargo.lock: added aes = "0.8".
  • docs/connection-gate-findings.md: corrected classification + new "LSX complete" section.
  • docs/HANDOFF-lsx-2026-07-02.md: this file.
  • captures/lsx-handshake-capture-2026-07-02.log: a captured live handshake plus the raw session ciphertext, kept as a reference sample for verifying the implementation.

openfut-launcher/openfut-hook

  • src/connect_hook.rs: added a PORT_LSX_NBO (3216) → PORT_LSX_TARGET_NBO (3217) arm in redirect_if_ea, plus result logging on the redirect path.

There is other pre-existing uncommitted work in these trees from before this session (e.g. bridge TLS/proxy changes, core changes). Do not sweep it into a commit without checking with the user. Confirm scope before committing anything.


How to reproduce the working LSX session

  1. Build the hook (redirect):
    cd openfut-launcher/openfut-hook
    cargo build --release --target x86_64-pc-windows-gnu
    
  2. Deploy it (back up first — already backed up once):
    SRC=openfut-launcher/openfut-hook/target/x86_64-pc-windows-gnu/release/openfut_hook.dll
    cp -f "$SRC" "/mnt/games/FIFA 23/version.dll"
    
  3. Build + run the bridge on 3217:
    cd openfut-bridge && cargo build --release
    LSX_ADDR=127.0.0.1:3217 RUST_LOG=openfut_bridge=debug \
      ./target/release/openfut-bridge > /tmp/bridge-lsx.log 2>&1 &
    
  4. Launch FIFA (user does this — umu/Steam via /home/alex/Desktop/launch-fifa23-live-editor.sh).
  5. Verify: ss -tnp | grep 3217 should show ESTAB FIFA23.exe ↔ openfut-bridge, and /tmp/bridge-lsx.log should show multiple LSX: dispatch … lines (not one garbage message).

Key facts / constants

Thing Value
EA App LSX port (FIFA connects here) 127.0.0.1:3216
Redirect target (our bridge LSX) 127.0.0.1:3217 (LSX_ADDR)
LSX AES-128-ECB key 000102030405060708090a0b0c0d0e0f
Our greeting key (challenge plaintext) cacf897a20b6d612ad0c05e011df52bb
Session seed rule first two ASCII chars of our ChallengeAccepted response hex, as raw bytes (e.g. "0f…"0x3066), NOT the parsed hex pair
Existing shim interception in-process, keyed on port 3216; loopback is shared (FIFA netns == host netns)

Small verification helpers (keyscan.py, seedscan.py) live in the session scratchpad — trivial to recreate from connection-gate-findings.md if needed.


Next steps (in priority order)

  1. Add a GetGameInfo GameInfoId=… handler to the bridge dispatcher (src/lsx.rs dispatch()). It currently falls back to the generic <Ok/> ("unknown request type"). FIFA tolerated that, but may need real responses to progress. This is the immediate iteration surface now that we can see FIFA's real requests.
  2. Watch how far FIFA advances with the LSX session satisfied — the next step is the Blaze/online layer (the old M2 ONLINE_STATUS_EVENT blocker). With LSX now handled by our bridge, that picture may change; re-evaluate M2 with FIFA actually reaching it.
  3. Port the seed fix into the hook's own src/lsx.rs if the in-process LSX path is ever revived — it has the same compute_seed bug.
  4. Decide on the redirect's permanence — right now it's a manual DLL swap. If LSX-via-bridge becomes the intended path, the launcher's setup/deploy flow should own it.

Open question for the user

We never captured what FIFA showed on screen during the successful run (advanced to a menu? sat at "connecting"? waited on GetGameInfo?). Ask, or observe on the next launch — it tells you whether LSX is fully satisfied or whether GetGameInfo is the next thing to address.