9f1fc1b47c
Add read-only preflight verifier and Windows-client documentation for the reimaged native-Windows FIFA17 client host (10.10.0.105). No launcher script: the native model is _fifa17.exe run as admin (RUNASADMIN + shortcut). Covers routing (openfut.cfg -> 10.10.0.120), rollback (version.dll swap), and the x64dbg RVA<->VA (ASLR) attach workflow (ImageBase 0x180000000 CardsDLL/powdll).
130 lines
7.5 KiB
PowerShell
130 lines
7.5 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
OpenFUT FIFA 17 Windows client preflight - READ ONLY.
|
|
|
|
.DESCRIPTION
|
|
Non-destructive verification of the native Windows FIFA 17 OpenFUT client on
|
|
this machine. It NEVER launches the game, never elevates, never writes to
|
|
game files, and never mutates any economy state. It only reads files,
|
|
registry, and performs TCP connect probes to the configured backend.
|
|
|
|
Exit code 0 = all PASS/WARN, 1 = one or more FAIL.
|
|
|
|
Native launch model (there is NO launcher script by design):
|
|
run C:\FIFA 17\_fifa17.exe as Administrator
|
|
(use the "FIFA 17 (OpenFUT)" shortcut, which carries the RunAsAdmin bit).
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$FifaRoot = 'C:\FIFA 17'
|
|
)
|
|
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
$ErrorActionPreference = 'SilentlyContinue'
|
|
|
|
# --- known-good fingerprints -------------------------------------------------
|
|
# Retail executable MUST NOT be modified/patched (Denuvo + anti-cheat sensitive).
|
|
$EXPECT_FIFA17_EXE_SHA256 = '29C31CEF12B0C3C2A7305220617C7B4FA139AB76B8C857851BDBE88987962899'
|
|
# Currently deployed OpenFUT hook (base-supply + VEH build). Update on redeploy.
|
|
$EXPECT_HOOK_SHA256 = '8844A6BCEE7BE37DD55B989246B312AF52FA711CCBC1220D25FEC64CBAD077D8'
|
|
$ROLLBACK_BAK = Join-Path $FifaRoot 'version.dll.stale-849k.bak'
|
|
|
|
$script:fail = 0
|
|
function Say([string]$level, [string]$msg) {
|
|
switch ($level) {
|
|
'PASS' { $c = 'Green' }
|
|
'WARN' { $c = 'Yellow' }
|
|
'FAIL' { $c = 'Red'; $script:fail++ }
|
|
default { $c = 'Gray' }
|
|
}
|
|
Write-Host ('[{0}] {1}' -f $level, $msg) -ForegroundColor $c
|
|
}
|
|
function Sha([string]$p) { if (Test-Path $p) { (Get-FileHash $p -Algorithm SHA256).Hash } else { $null } }
|
|
|
|
Write-Host '=== OpenFUT FIFA 17 Windows client preflight (read-only) ===' -ForegroundColor Cyan
|
|
Say 'INFO' ("host={0} user={1} {2}" -f $env:COMPUTERNAME, $env:USERNAME, (Get-CimInstance Win32_OperatingSystem).Caption)
|
|
|
|
# --- 1. FIFA install + retail exe integrity ---------------------------------
|
|
$exe = Join-Path $FifaRoot 'FIFA17.exe'
|
|
$loader = Join-Path $FifaRoot '_fifa17.exe'
|
|
if (Test-Path $exe) {
|
|
$h = Sha $exe
|
|
if ($h -eq $EXPECT_FIFA17_EXE_SHA256) { Say 'PASS' "FIFA17.exe present and unmodified ($($h.Substring(0,16))...)" }
|
|
else { Say 'FAIL' "FIFA17.exe hash MISMATCH - retail exe changed! got $($h.Substring(0,16))... expected $($EXPECT_FIFA17_EXE_SHA256.Substring(0,16))..." }
|
|
} else { Say 'FAIL' "FIFA17.exe missing at $exe" }
|
|
if (Test-Path $loader) { Say 'PASS' "native loader _fifa17.exe present ($((Sha $loader).Substring(0,16))...)" }
|
|
else { Say 'FAIL' "_fifa17.exe (native loader) missing - cannot launch" }
|
|
|
|
# --- 2. companion DLLs -------------------------------------------------------
|
|
$companions = 'CardsDLL_Win64_retail.dll','powdll_Win64_retail.dll','sysdll_Win64_retail.dll',
|
|
'FootballCompEng_Win64_retail.dll','stp-origin_emu.dll','stp-selector.exe'
|
|
foreach ($c in $companions) {
|
|
$p = Join-Path $FifaRoot $c
|
|
if (Test-Path $p) { Say 'PASS' "companion present: $c" } else { Say 'FAIL' "companion MISSING: $c" }
|
|
}
|
|
|
|
# --- 3. OpenFUT hook (version.dll) + rollback backup ------------------------
|
|
$hook = Join-Path $FifaRoot 'version.dll'
|
|
if (Test-Path $hook) {
|
|
$hh = Sha $hook
|
|
if ($hh -eq $EXPECT_HOOK_SHA256) { Say 'PASS' "hook version.dll deployed (expected build $($hh.Substring(0,16))...)" }
|
|
else { Say 'WARN' "hook version.dll present but hash differs from recorded build ($($hh.Substring(0,16))...) - may be a newer/older hook" }
|
|
$bytes = [IO.File]::ReadAllBytes($hook); $ascii = [Text.Encoding]::ASCII.GetString($bytes)
|
|
$markers = @('OpenFUT','fifa17','CardsDLL','SBC_DISPATCH') | Where-Object { $ascii -match [regex]::Escape($_) }
|
|
if ($markers.Count -ge 3) { Say 'PASS' "hook markers found: $($markers -join ', ')" }
|
|
else { Say 'WARN' "hook markers thin: $($markers -join ', ') - is this the OpenFUT hook?" }
|
|
} else { Say 'FAIL' "hook version.dll NOT deployed - client will run vanilla (no OpenFUT)" }
|
|
if (Test-Path $ROLLBACK_BAK) {
|
|
if ((Sha $ROLLBACK_BAK) -ne (Sha $hook)) { Say 'PASS' "rollback backup present and differs from live: $(Split-Path $ROLLBACK_BAK -Leaf)" }
|
|
else { Say 'WARN' "rollback backup equals live version.dll - rollback would be a no-op" }
|
|
} else { Say 'WARN' "no rollback backup ($(Split-Path $ROLLBACK_BAK -Leaf)) - keep one before redeploying the hook" }
|
|
|
|
# --- 4. routing config + backend reachability -------------------------------
|
|
$cfg = Join-Path $FifaRoot 'openfut.cfg'
|
|
$host120 = $null; $ports = @()
|
|
if (Test-Path $cfg) {
|
|
$kv = @{}; foreach ($l in Get-Content $cfg) { if ($l -match '^\s*([^=#]+)=(.+)$') { $kv[$matches[1].Trim()] = $matches[2].Trim() } }
|
|
$host120 = $kv['host']
|
|
Say 'PASS' "openfut.cfg routing: host=$($kv['host']) https=$($kv['https_port']) redirector=$($kv['blaze_redirector_port']) blaze=$($kv['blaze_main_port'])"
|
|
foreach ($k in 'https_port','blaze_redirector_port','blaze_main_port') { if ($kv[$k]) { $ports += [int]$kv[$k] } }
|
|
if ($kv['blaze_main_port'] -eq '42130') { Say 'WARN' 'blaze_main_port=42130 targets PRODUCTION - repoint to a staging port before match/economy testing' }
|
|
} else { Say 'WARN' "openfut.cfg absent - hook uses its baked-in default host" }
|
|
if ($host120) {
|
|
foreach ($p in $ports) {
|
|
$t = New-Object Net.Sockets.TcpClient
|
|
try {
|
|
$ar = $t.BeginConnect($host120, $p, $null, $null)
|
|
if ($ar.AsyncWaitHandle.WaitOne(2500) -and $t.Connected) { Say 'PASS' "backend reachable ${host120}:$p" }
|
|
else { Say 'FAIL' "backend UNREACHABLE ${host120}:$p" }
|
|
} catch { Say 'FAIL' "backend probe error ${host120}:$p - $($_.Exception.Message)" } finally { $t.Close() }
|
|
}
|
|
}
|
|
|
|
# --- 5. login persona (stp origin emulator) ---------------------------------
|
|
$ini = Join-Path $FifaRoot 'stp-origin_emu.ini'
|
|
if (Test-Path $ini) {
|
|
$persona = (Get-Content $ini | Select-String 'PersonaId|PersonaName') -join ' '
|
|
Say 'PASS' "login emulator config: $persona"
|
|
} else { Say 'FAIL' "stp-origin_emu.ini missing - no login persona" }
|
|
|
|
# --- 6. native launcher elevation setup -------------------------------------
|
|
$lk = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers'
|
|
$layer = (Get-ItemProperty $lk).$loader
|
|
if ($layer -match 'RUNASADMIN') { Say 'PASS' "_fifa17.exe RUNASADMIN flag set ($layer)" }
|
|
else { Say 'WARN' '_fifa17.exe has no RUNASADMIN flag - launch must be manual "Run as administrator"' }
|
|
$sc = Join-Path $env:USERPROFILE 'Desktop\FIFA 17 (OpenFUT).lnk'
|
|
if (Test-Path $sc) { Say 'PASS' "desktop launcher shortcut present: $(Split-Path $sc -Leaf)" }
|
|
else { Say 'WARN' 'no desktop launcher shortcut' }
|
|
|
|
# --- 7. RE toolchain ---------------------------------------------------------
|
|
$x = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Depth 4 -Include x64dbg.exe -Attributes !ReparsePoint -EA SilentlyContinue | Select-Object -First 1 -Expand FullName
|
|
if (-not $x) { $x = (Get-Command x64dbg.exe -EA SilentlyContinue).Source }
|
|
if ($x) { Say 'PASS' "x64dbg present: $x (v$((Get-Item $x).VersionInfo.FileVersion))" } else { Say 'WARN' 'x64dbg not located - install for runtime RE' }
|
|
$cargo = (Get-Command cargo -EA SilentlyContinue).Source
|
|
if ($cargo) { Say 'PASS' "rust toolchain: $cargo" } else { Say 'WARN' 'cargo not found - needed to rebuild the hook natively' }
|
|
|
|
# --- summary -----------------------------------------------------------------
|
|
Write-Host ''
|
|
if ($script:fail -eq 0) { Write-Host 'PREFLIGHT: PASS (no blocking failures)' -ForegroundColor Green; exit 0 }
|
|
else { Write-Host "PREFLIGHT: FAIL ($script:fail blocking issue(s))" -ForegroundColor Red; exit 1 }
|