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) <noreply@anthropic.com>
This commit is contained in:
@@ -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: `<Challenge>` / `<ChallengeResponse>` /
|
||||||
|
`<ChallengeAccepted>`, `sender="EALS"`, `ContentId 16115019`.
|
||||||
|
2. River/PIN telemetry `<session type=boot>` 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.
|
||||||
@@ -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).
|
||||||
Reference in New Issue
Block a user