Files
OpenFUT/tools/windows/README.md
T
funman300 286a44461d tools/windows: scoped DNS resolver for the FIFA 17 roster hostname
FIFA 17's ProtoSSL verifies the roster certificate by dNSName only, so the
client must reach the roster as winter15.gosredirector.ea.com. Retested on
Windows 2026-08-23: an IP-addressed roster host is refused even though the
certificate carries IP Address:10.10.0.120 as a SAN.

Public DNS points that name at EA's dead 159.153.51.20, so the client has to
resolve it to us. scoped-dns.py pins exactly that one name and forwards every
other query upstream verbatim, so a client pointed at it cannot lose general
resolution -- verified against www.microsoft.com, github.com and
www.msftconnecttest.com.

Paired with a Windows NRPT rule rather than a hosts entry: per-name, auditable
via Get-DnsClientNrptRule, and revertible in one command. A hosts edit on this
machine had previously taken its whole internet down.
2026-08-23 01:34:13 +00:00

143 lines
6.6 KiB
Markdown

# OpenFUT FIFA 17 - native Windows client
The FIFA 17 client host (`10.10.0.105`, Windows 11 Pro) runs FIFA 17 **natively**
(no Wine/Proton/umu). This directory holds the read-only preflight verifier and
documents the native launch/routing/rollback model.
## Install layout (`C:\FIFA 17`)
| File | Role |
|---|---|
| `FIFA17.exe` | retail game exe (sha256 `29C31CEF…`). **Never modify/patch.** ImageBase `0x140000000`. |
| `_fifa17.exe` | native crack loader (Chemicalflood). This is what you launch. `asInvoker` manifest -> must be elevated externally. |
| `version.dll` | **OpenFUT hook** (in-process via the version.dll load-order hijack). ImageBase `0x180000000`. |
| `version.dll.stale-849k.bak` | **rollback** copy of the previous hook. |
| `CardsDLL_Win64_retail.dll` | FUT card/SBC/kit logic. ImageBase `0x180000000`. |
| `powdll_Win64_retail.dll` | Pack-Opening-World (EASFC store). ImageBase `0x180000000`. |
| `sysdll_Win64_retail.dll` | EA networking / ProtoSSL (cert, ea.com). |
| `stp-origin_emu.dll` + `stp-origin_emu.ini` | Origin/LSX login emulator (in-process; opens LSX `:4216` locally at runtime). Persona configured in the `.ini`. |
| `stp-selector.exe` | ssl/LSX selector companion. |
| `openfut.cfg` | operator-facing routing override (see below). |
## Launch (native - there is NO launcher script by design)
Run `C:\FIFA 17\_fifa17.exe` **as Administrator**. The correct, reproducible way:
- Double-click the **"FIFA 17 (OpenFUT)"** shortcut (Desktop and Start Menu).
It targets `_fifa17.exe`, working dir `C:\FIFA 17`, with the RunAsAdmin bit set.
- `_fifa17.exe` is also flagged `RUNASADMIN` in
`HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers`,
so any launch (Explorer double-click included) elevates via UAC.
On launch the Windows loader maps `version.dll` from the game directory (hijack),
`stp-origin_emu.dll` emulates Origin login for the configured persona, and the
hook redirects EA endpoints to the OpenFUT backend.
> Do **not** wrap the launch in a script. The elevation + shortcut is the
> supported mechanism. FIFA under native Windows also ignores synthetic input,
> so in-game steps are performed by the operator one at a time.
### OpenFUT Launcher (GUI)
The `openfut-launcher` egui app runs natively on Windows (built for
`x86_64-pc-windows-gnu`; the Linux Proton path is `cfg`-gated out). It is the
one-button front end: it checks the backend, reconciles `openfut.cfg` from its
settings, and starts the game.
- Binary: `C:\OpenFUT\openfut-launcher.exe`; config: `%APPDATA%\openfut-launcher\config.json`.
- Launch it from the **"OpenFUT Launcher"** shortcut (Desktop / Start Menu). The
launcher itself is flagged `RUNASADMIN`, so it elevates once at start; the game
it spawns inherits that elevation (no second UAC prompt, no crack loader
"run as admin" failure).
- On Windows the launcher does NOT spawn LSX/autopatch (they are in-process:
`stp-origin_emu.dll` + the `version.dll` hook) and does NOT arm the host
(routing is purely `openfut.cfg`, which it writes into `C:\FIFA 17`).
- Rebuild from Linux: `cargo build -p openfut-launcher --release --target x86_64-pc-windows-gnu`.
## Routing (`openfut.cfg`)
```
host=10.10.0.120
https_port=8443
blaze_redirector_port=42127
blaze_main_port=42130
```
The hook carries `10.10.0.120` as its baked-in default; `openfut.cfg` is the
override. `10.10.0.120` hosts **both** production and staging.
> **Production safety:** `blaze_main_port=42130` is the **production** Blaze.
> Before any match/economy exercise, repoint `blaze_main_port` (and the matching
> UTAS/HTTPS route) to the staging port so no traffic reaches the prod container.
> The preflight raises a WARN whenever `42130` is configured.
## Rollback
The hook is a single file swap; no installer state.
```powershell
# disable OpenFUT hook (restore previous DLL)
Copy-Item 'C:\FIFA 17\version.dll' 'C:\FIFA 17\version.dll.disabled.bak' -Force
Copy-Item 'C:\FIFA 17\version.dll.stale-849k.bak' 'C:\FIFA 17\version.dll' -Force
# re-arm: copy the desired hook build over version.dll again
```
Always keep a `*.bak` of the live hook before redeploying (the preflight checks
that a rollback backup exists and differs from the live DLL).
## Roster / "FUT Squad Update" — the client MUST reach the roster by HOSTNAME
If FUT fails with **"An error occurred downloading the FUT Squad Update"**, the
client could not fetch `https://<roster>/fifa17/fut/rosterupdate.xml`.
FIFA 17's ProtoSSL verifies that certificate by **dNSName only**. Pointing the
roster at an IP does **not** work even though our certificate carries
`IP Address:10.10.0.120` in its SANs — this was retested on Windows on
2026-08-23 and rejected. Do not retry an IP roster host, and do not reissue the
certificate for an IP SAN. The roster must be reached as
`winter15.gosredirector.ea.com`, which our certificate does carry as a dNSName.
Public DNS resolves that name to EA's dead `159.153.51.20`, so the client has to
be told to resolve it to us. **Use an NRPT rule, not the hosts file.** A hosts
edit on this machine previously took its entire internet down; NRPT is per-name,
auditable with `Get-DnsClientNrptRule`, and reverts in one command.
On the server, run the scoped resolver (needs root for UDP 53):
```bash
sudo python3 tools/windows/scoped-dns.py
```
It answers **only** `winter15.gosredirector.ea.com` and forwards every other
query upstream verbatim, so it cannot strand a client that is pointed at it.
Then start Blaze with `OPENFUT_ROSTER_HOST=winter15.gosredirector.ea.com:8081`.
On the client, as Administrator:
```powershell
Add-DnsClientNrptRule -Namespace "winter15.gosredirector.ea.com" -NameServers "10.10.0.120"
# revert:
Get-DnsClientNrptRule | Where-Object Namespace -eq "winter15.gosredirector.ea.com" | Remove-DnsClientNrptRule -Force
```
## Preflight
`openfut-client-preflight.ps1` is **read-only**: it never launches the game,
never elevates, never writes game files, never mutates economy state. It verifies
the retail exe hash, companion DLLs, hook + rollback, routing + backend
reachability, login persona, launcher elevation, and the RE toolchain
(x64dbg, cargo). Exit 0 = OK, 1 = blocking failure.
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File .\openfut-client-preflight.ps1
```
## Runtime RE (x64dbg)
See the Vault note **`02 Reverse Engineering/FIFA 17/Windows Client Runtime & x64dbg.md`**
for the attach workflow and the RVA<->VA (ASLR) math. In short: these modules'
preferred ImageBase is `0x180000000` (`0x140000000` for `FIFA17.exe`); in x64dbg
a module name evaluates to its runtime (ASLR) base, so a Ghidra address maps to a
breakpoint as `bp CardsDLL_Win64_retail.dll+<RVA>` where
`RVA = ghidra_addr - 0x180000000`.