Files
OpenFUT-Bridge/CLAUDE.md
T
funman300 bc6612697a feat: add ProtoSSL RE tooling and FIFA 23 in-process hook
Add the reverse-engineering work for FIFA 23 online integration:

- tools/protossl-scan: read-only memory scanner that confirms the
  DirtySDK/ProtoSSL transport, cross-references strings to code
  (xref/xref-str), and disassembles the enclosing function (disasm).
  Located _ProtoSSLSendPacket at FIFA23.exe+0xEFA530 (plaintext TLS
  record assembler) via the "_ProtoSSLSendPacket" debug string xref.

- openfut-hook: version.dll proxy (forwards all 17 real exports) that
  injects into FIFA 23 and installs an inline detour on
  _ProtoSSLSendPacket, plus connect/DNS (getaddrinfo) capture and local
  LSX/redirect listeners. Logs to C:\openfut\hook.log.

- CLAUDE.md: bridge project context + the gate-sequence task roadmap.

Findings so far: with the anadius offline emulator the game never
attempts the online Blaze connection (local auth gate), so capture of
live Blaze frames is blocked pending an online-session fake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 17:09:26 -07:00

191 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenFUT Bridge — Claude Code project context
Read this first. It's the standing context for every task in this project. Each
working session will give you ONE bounded task plus a verification clause; this
file is the background that stays true across all of them.
## What this project is
OpenFUT is an **offline FIFA 23 FUT (Ultimate Team) emulator** for single-player
game preservation. EA permanently shut down FIFA 23's online servers in October
2025, which removed FUT. This project lets a legitimately-owned copy run FUT
against a **local emulated backend** instead of EA's (dead) servers.
It has two repos:
- **OpenFUT Core** — the game-independent FUT economy backend (already largely built).
- **OpenFUT Bridge** — the FIFA 23 integration / reverse-engineering layer (this work).
## Hard constraints (do not violate)
- **Clean-room only.** Everything is derived from observing the running client's
own behaviour. NEVER use, reference, or reproduce leaked EA source code (e.g.
the 2021 FIFA 21 / Blaze leak). If a task seems to need it, stop and say so.
Clean-room provenance is the legal foundation of the whole project.
- **Mark uncertainty, don't invent.** Several things are genuinely unconfirmed:
the Fire2 packet framing, ProtoSSL non-blocking return values, and FIFA 23's
Blaze component/command IDs. When you don't know a value, leave a clearly
labelled `TODO/CONFIRM` rather than guessing a confident-looking number.
- **Verify against the client.** The dead servers mean responses are *synthesized
and tested against the live offline client*, never captured from EA. The client
is the oracle: a gate is "done" when the client advances to the next command.
## Architecture
```
FIFA 23 client (offline, native Windows)
| ProtoSSLConnect / ProtoSSLSend / ProtoSSLRecv (in-process)
openfut_hook.dll — fakes the connection, captures requests, injects responses
| plain localhost TCP, length-prefixed frames (no TLS)
blaze_brain (Rust) — decodes requests, crafts Blaze responses <-- iteration surface
|
OpenFUT Core — supplies real FUT economy data for the FUT gates
```
Why in-process (not a localhost TLS server): FIFA 23's ProtoSSL uses modern TLS
with cert pinning, so a fake server gets its cert rejected. Hooking ABOVE the
crypto (ProtoSSLSend/Recv take/return plaintext) sidesteps TLS entirely.
## The entry sequence (the gates to reach FUT)
The client runs these in order; each must be satisfied before the next fires:
1. **LSX** (port 3216, plaintext loopback) — launcher→game bootstrap.
2. **Blaze redirector** — returns a server host/port.
3. **Blaze preauth** (UTIL) — config / component list.
4. **Blaze login** (AUTHENTICATION) — persona, session key, UID.
5. **Blaze postauth** (UTIL) — telemetry/ticker; "fully online".
6. **FUT entry check** — FIFA-specific eligibility/entitlement wall.
7. **FUT hub load** — club/squad over REST; hand off to OpenFUT Core.
Gates 25 are largely static/replayable (the client validates little). Gates 67
need internally-consistent data and connect to OpenFUT Core.
## Environment
- Native Windows boot (chosen for predictable PE/hooking behaviour over Proton).
- FIFA 23, with EA Anticheat in its offline/neutralized state. Do NOT assume a
task is safe to hook unless EAAC is confirmed neutralized.
- Rust is the primary language. Hook = `cdylib`, Windows target. Brain = portable.
- Self-hosted Gitea (git.aleshym.co, org Quaternions). Self-hosted CI runner.
## How to work here
- One rung at a time. Don't run ahead into a gate that depends on an unconfirmed
earlier answer.
- When decoding a frame, work from REAL captured bytes the user pastes in — not
from a guessed layout. Ask for the bytes if they're not provided.
- End each change with how the user verifies it on the client.
# OpenFUT Bridge — Task prompts (run in order)
Each task is its own Claude Code session. Paste the task, attach the named
starting file(s), and don't move to the next until the verification clause passes.
The project CLAUDE.md is assumed to be in context.
---
## TASK 1 — Confirm the transport (read-only memory scan)
**Goal:** prove whether FIFA 23 uses EA DirtySDK / ProtoSSL before we build any
hook around it. Read-only; no hooking, patching, or injection.
**Do this:**
Write a standalone Windows console program in Rust (target
`x86_64-pc-windows-msvc` or `-gnu`) that:
1. Finds the running FIFA 23 process by name (and accepts a PID argument).
2. Enumerates its modules and committed memory regions (e.g. `EnumProcessModules`
/ `VirtualQueryEx`), readable regions only.
3. Reads memory with `ReadProcessMemory` in chunks (with small overlap so a
marker spanning a chunk boundary is still found).
4. Searches for these ASCII markers and prints each hit with its absolute address:
`protossl:`, `ProtoSSLSend`, `ProtoSSLRecv`, `ProtoSSLConnect`,
`gosredirector`, `DirtySDK`, `blaze`.
5. Prints a summary: which markers were found, and a clear verdict line
("ProtoSSL present" vs "no ProtoSSL markers found").
Keep it dependency-light (the `windows` crate is fine). Comment it for a Rust
beginner. It must only read.
**Verification:** with FIFA 23 running and sitting at the main menu, the program
prints whether the ProtoSSL markers are present. If `protossl:` and the
send/recv strings appear, the transport is confirmed and we proceed. If nothing
appears after the menu has loaded, STOP — we rethink the transport, don't build
the hook.
**Note:** reach the main menu before scanning; the networking code/strings may
not be paged in at the title screen.
---
## TASK 2 — Loadable DLL shell (prove we can get code in)
**Goal:** a `version.dll` proxy that loads into FIFA 23 and runs our code, before
any hook logic exists. This isolates "can we inject at all" from "is the hook
correct".
**Do this:**
Create a Rust `cdylib` (Windows target) that:
1. Exports the functions a real `version.dll` exports, forwarding each to the
system `version.dll` (proxy/sideload pattern). List the needed exports and
implement the forwarding.
2. In `DllMain`, on `DLL_PROCESS_ATTACH`, spawns a thread (NOT work in DllMain
itself — loader lock) that writes a line to a log file in a known path, e.g.
`C:\openfut\hook.log`, with a timestamp.
3. Provide the `Cargo.toml` (`crate-type = ["cdylib"]`) and the exact build
command.
Clean-room: this is generic proxy/loader scaffolding, nothing EA-derived.
**Verification:** drop the built DLL next to the FIFA 23 executable, launch the
game, and confirm `hook.log` gets the timestamped line. Game still reaches the
menu normally. If it crashes or the line never appears, fix the proxy/forwarding
before continuing.
**Caution:** confirm EAAC is in its offline/neutralized state before loading the
DLL. Do not load it into an anticheat-active session.
---
## TASK 3 — One landing hook on ProtoSSLSend
**Goal:** prove we can hook a ProtoSSL function and see real outbound frames.
Just one function, and it calls the original (passive observation).
**Do this:**
Extend the Task 2 DLL:
1. Add the `retour` crate. Resolve the `ProtoSSLSend` address — first pass: use
the absolute address Task 1 reported, converted to a module-relative offset
plus the live module base. (We'll switch to a byte-pattern scan later for
patch-resilience; leave a TODO for that.)
2. Install a `retour` inline detour on `ProtoSSLSend` with signature
`extern "C" fn(*mut c_void, *const u8, i32) -> i32` (x64 = one calling
convention; `extern "C"` is correct).
3. In the detour: log `length` and the first ~32 bytes of the buffer as hex,
then CALL THE ORIGINAL and return its result (do not block or alter traffic
yet).
Mark the ProtoSSL return-value conventions and the eventual pattern-scan as
`TODO/CONFIRM` per the project rules.
**Verification:** launch the game, attempt to go online / load FUT, and confirm
`hook.log` shows ProtoSSLSend calls with non-trivial byte dumps — these are the
client's real outbound Blaze frames (still TLS-bound on the wire, but plaintext
here, which is the whole point). Seeing real frames = hooking works, and we now
have actual bytes to decode in later tasks. Paste a few of those captured frames
into the next session.
---
## What to attach to each task
- Task 1: nothing (fresh program), or the Linux `protossl_scan.rs` as a logic
reference to port.
- Task 2: nothing, or your existing `version.dll` proxy shell if you have one.
- Task 3: the Task 2 DLL, plus the `openfut_hook_sketch.rs` as the structural
reference, plus the address Task 1 reported.
Once Task 3 yields real captured frames, later tasks (the brain handlers per
gate) should always include the actual pasted bytes — decoding real frames is far
more reliable than guessing the Fire2 layout.