Compare commits

...

1 Commits

Author SHA1 Message Date
funman300 49b3030e34 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>
2026-06-29 18:00:27 -07:00
2 changed files with 156 additions and 0 deletions
+65
View File
@@ -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.
+91
View File
@@ -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 (M1M7). 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 M1M5; **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 M1M5 are documented — valuable even if A stalls.
- **A (playable AI FUT)** requires M1M7.
## 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).