From 49b3030e34228f529a92c3c5910b29e2914e467a Mon Sep 17 00:00:00 2001 From: funman300 Date: Mon, 29 Jun 2026 18:00:27 -0700 Subject: [PATCH] docs: connection-gate findings + roadmap (strategy pivot) Stop fighting anadius's offline verdict. Document the clean-room findings (the gate is an upstream in-process Ebisu connection-state check, not socket traffic) and a milestone roadmap with two first-class outcomes: full playable AI FUT (A) and a clean-room spec deliverable (B). Name M3 (first ProtoSSL plaintext on the real Blaze connection) as the smallest end-to-end proof. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/connection-gate-findings.md | 65 +++++++++++++++++++++++ docs/roadmap.md | 91 ++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 docs/connection-gate-findings.md create mode 100644 docs/roadmap.md diff --git a/docs/connection-gate-findings.md b/docs/connection-gate-findings.md new file mode 100644 index 0000000..01fe975 --- /dev/null +++ b/docs/connection-gate-findings.md @@ -0,0 +1,65 @@ +# Connection-gate findings (clean-room) + +**Status:** observed behaviour only — derived from running the client and reading +the repack's own files. No EA source used. Unconfirmed values are marked +`TODO/CONFIRM` rather than guessed. + +## Components (observed) + +| Component | Role | +|---|---| +| `FIFA23.exe` | Game. Statically links EA's **Ebisu SDK** (online) and **DirtySDK/ProtoSSL** (transport). Loads at fixed base `0x140000000` — no ASLR seen across launches. | +| `_ProtoSSLSendPacket` @ `FIFA23.exe+0xEFA530` | DirtySDK TLS record assembler — plaintext in, encrypts in place. Already located + hooked. | +| `anadius64.dll` | anadius EA-app/Origin **LSX server** emulator (ASLR'd). Provides offline DRM / entitlements / persona so the game *launches*; deliberately keeps it **offline**. | +| `FakeEAACLauncher` | Anti-cheat bypass only. Irrelevant to the online gate. | + +## Observed online-startup flow + +1. Ebisu SDK opens LSX socket(s) to anadius; a **challenge/response handshake** + completes — captured XML: `` / `` / + ``, `sender="EALS"`, `ContentId 16115019`. +2. River/PIN telemetry `` is emitted. +3. **No further socket traffic.** Clicking Ultimate Team → "connecting to the EA + Servers…" → **zero** network attempts (no Blaze DNS, no `connect`, nothing on + `send`/`recv`/`WSASend`/`WSARecv`) → falls back to offline. + +## Conclusion: the decision is upstream and in-process + +- The online/offline verdict is delivered through anadius's **in-process + detoured Ebisu calls**, not socket messages. (No `GetAuthCode`/`GoOnline`/ + entitlement query appears on any socket, sync or async.) +- The game therefore **never reaches DirtySDK/ProtoSSL for Blaze** — it aborts + before any `ProtoSSLConnect(gosredirector…)`. The gate is an **Ebisu-SDK + connection-state / online-session check upstream of the transport.** +- `ONLINE_ACCESS` is a `Blaze::Nucleus::EntitlementType` (enum value `1`). + anadius's `GoOnline` LSX handler (`anadius64.dll+0x2BB90`) is a success stub; + `anadius64.dll+0xB6B1` is a large entitlement/profile builder that *does* + reference `ONLINE_ACCESS`. Reverse-engineering that entitlement-status logic + is the **wrong fight** (see strategy). + +## Strategy (decided) + +Do **not** make anadius report "online." anadius exists to keep the game +offline, and it can't be removed without breaking launch/DRM. Instead: + +> Let the game run its **real** online flow and answer that flow ourselves via +> the hook + brain. Target the Ebisu connection-state check the FUT-entry path +> polls; make the game *pass* it so it issues the real `ProtoSSLConnect` to the +> Blaze redirector → our redirect + ProtoSSL hook capture the real frames. + +This deletes the "reverse-engineer anadius's entitlement logic" problem. + +## Next RE step (converges with the ProtoSSL hook) + +1. Locate and **read-only hook `ProtoSSLConnect`** (same DirtySDK module and + technique that found `_ProtoSSLSendPacket`). Confirms the game never + initiates the Blaze connection (pins the gate strictly upstream) and gives us + the exact symbol that will flip from "never called" to "called" on success. +2. Locate the Ebisu **connection-state getter** the FUT-entry / "connecting" UI + polls. Candidate string anchors (observed): `ONLINE_STATUS_EVENT`, + `GoOnline` result handling, the "connecting to the EA Servers" UI trigger. +3. Determine the minimal intervention to make that getter report **connected** + (out-hook it in our `version.dll`, winning over anadius's detour) so the game + proceeds to `ProtoSSLConnect`. + - `TODO/CONFIRM`: whether out-hooking the getter is sufficient, or secondary + checks (auth-token presence) also gate the attempt. diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..c2fdbe4 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,91 @@ +# OpenFUT Bridge roadmap — from here to "Squad Battles loads" + +Two **first-class** outcomes (not one goal + a consolation prize): + +- **A. Full playable AI FUT** — the emulator build (M1–M7). Realistically a + multi-month, expert-level reverse-engineering effort. +- **B. Clean-room spec deliverable** — a documented map of the auth / Blaze / + ProtoSSL / Fire2 surface (transport, gates, framing, decision points). Produced + incrementally as the findings from M1–M5; **finishable and valuable on its + own**, and the foundation any future emulator needs. + +Every milestone's "done" is a **client-observable** result. Unconfirmed +dependencies are flagged. + +## Done so far + +- In-process `version.dll` hook (injects, forwards all 17 real exports). +- Transport confirmed: DirtySDK/ProtoSSL. `_ProtoSSLSendPacket` @ + `FIFA23.exe+0xEFA530` hooked (plaintext-capture ready). +- `connect` / DNS / LSX (`send`/`recv` + `WSASend`/`WSARecv`) capture; mutexed log. +- Gate identified: **upstream Ebisu connection-state, in-process** (see + `connection-gate-findings.md`). +- RE toolkit: `protossl-scan` (scan / xref / disasm / module+offset). + +## M1 — Locate the connection-state decision point · Outcome B core +- Read-only hook `ProtoSSLConnect`; find the Ebisu connection-state getter the + FUT-entry path polls. +- **Done:** we can name the exact function/return that gates "attempt online." +- Unknown: coupling to anadius's detour. **Effort:** ~days. + +## M2 — Flip the gate (force "connected") · pure gate-flip proof +- Out-hook the getter / patch the polled state so the game attempts the real + connection. +- **Done (observable):** the game emits a DNS lookup / `connect` for the Blaze + redirector (`gosredirector.*`). +- Unknown: a secondary auth-token gate may also block. `TODO/CONFIRM`. + **Effort:** ~days. + +## M3 — First real ProtoSSL plaintext on the Blaze connection · SMALLEST END-TO-END PROOF (see "Smallest milestone") +- Our redirect catches the Blaze connect; the ProtoSSL hook logs the first + plaintext it emits (the TLS **ClientHello** to the redirector). +- **Done:** `hook.log` shows the ClientHello from the *real* Blaze connection. +- Note: this is a TLS handshake frame, **not yet** a Blaze/Fire2 app-data frame. + **Effort:** small once M2 lands. + +## M4 — Answer the redirector + decode first Fire2 frame · Outcome B: first decode +- Inject a response via the ProtoSSL recv side so the client advances; decode + the first Blaze/Fire2 request frame from real captured bytes. +- **Done:** the client advances past the redirector (sends the next gate's frame). +- Unknown (**BIG**): **Fire2 framing UNCONFIRMED**; **ProtoSSL recv-injection / + TLS-bypass convention UNCONFIRMED**; **Blaze component/command IDs UNCONFIRMED**. + **Effort:** high. + +## M5 — Blaze preauth / login / postauth (online session) · Outcome B: full auth surface +- Answer UTIL preauth, AUTHENTICATION login (reusing anadius's persona surface), + UTIL postauth. +- **Done:** client reports online / reaches the FUT entry check. +- Depends on M4 framing. **Effort:** high. + +## M6 — FUT entry + hub load (route to OpenFUT Core) · Outcome A +- Answer the FUT eligibility check; serve the FUT hub (club/squad) from OpenFUT + Core via the bridge. +- **Done:** the FUT hub UI loads (club/squad screen). +- Depends on Core's FUT REST surface. **Effort:** high. + +## M7 — Squad Battles (AI FUT) · Outcome A goal +- Wire Squad Battles match setup / rewards against Core. +- **Done:** a Squad Battles match starts and rewards apply. +- **Effort:** medium-high after M6. + +## Outcome mapping +- **B (spec)** completes as M1–M5 are documented — valuable even if A stalls. +- **A (playable AI FUT)** requires M1–M7. + +## Smallest provable milestone (step 4) + +Refined from the proposed candidate. The single smallest result that validates +the whole architecture end-to-end: + +> **M3 — the client emits its first ProtoSSL plaintext onto the _real_ Blaze +> connection (the ClientHello to the redirector), captured by our hook.** + +It proves both halves at once: (1) we got the game past its connection-state +check — it went online **for real**; and (2) our redirect + ProtoSSL hook +capture real plaintext from that connection. + +It deliberately stops short of the candidate's "first **Blaze** frame" (a Fire2 +app-data message), which requires answering the TLS handshake (M4) and depends +on the unconfirmed Fire2 / recv-injection work. ClientHello capture needs none +of that — making it the smallest, safest proof. The first Fire2 frame is the +immediate follow-on (M4).