feat: add guarded FIFA 17 SBC diagnostics
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
//! FIFA 17 injection path (feature = "fifa17").
|
||||
//!
|
||||
//! This is a *separate, minimal* entry point from the FIFA-23 `install_hooks`.
|
||||
//! FIFA 17 is a different game with different in-memory structures, so we run NONE
|
||||
//! of the FIFA-23 connect/LSX/origin_spy/dial logic here — that would at best
|
||||
//! no-op and at worst crash. For now this proves the version.dll hijack actually
|
||||
//! loads us into FIFA17.exe and dumps the module map, which we need to locate
|
||||
//! DirtySDK/ProtoSSL's cert-verify function (the next milestone: patch it so the
|
||||
//! secure Blaze redirector's TLS handshake succeeds against our bridge cert).
|
||||
//!
|
||||
//! Everything here is read-only except the (not-yet-enabled) cert-verify patch.
|
||||
|
||||
use crate::write_log;
|
||||
use windows_sys::Win32::Foundation::{CloseHandle, INVALID_HANDLE_VALUE};
|
||||
use windows_sys::Win32::System::Diagnostics::ToolHelp::{
|
||||
CreateToolhelp32Snapshot, Module32FirstW, Module32NextW, MODULEENTRY32W, TH32CS_SNAPMODULE,
|
||||
TH32CS_SNAPMODULE32,
|
||||
};
|
||||
use windows_sys::Win32::System::LibraryLoader::GetModuleHandleA;
|
||||
|
||||
/// Read the SizeOfImage from a module's in-memory PE headers.
|
||||
unsafe fn size_of_image(base: usize) -> u32 {
|
||||
if base == 0 {
|
||||
return 0;
|
||||
}
|
||||
// DOS header -> e_lfanew (i32 @ 0x3c) -> PE header. SizeOfImage is in the
|
||||
// optional header at offset 0x50 from the PE signature (same for PE32/PE32+).
|
||||
let e_lfanew = *((base + 0x3c) as *const i32);
|
||||
let pe = base + e_lfanew as usize;
|
||||
// sanity: 'PE\0\0'
|
||||
if *(pe as *const u32) != 0x0000_4550 {
|
||||
return 0;
|
||||
}
|
||||
*((pe + 24 + 0x38) as *const u32) // opt header +0x38 = SizeOfImage
|
||||
}
|
||||
|
||||
fn wide_to_string(w: &[u16]) -> String {
|
||||
let end = w.iter().position(|&c| c == 0).unwrap_or(w.len());
|
||||
String::from_utf16_lossy(&w[..end])
|
||||
}
|
||||
|
||||
/// Enumerate loaded modules (name, base, size) via ToolHelp and log them.
|
||||
unsafe fn dump_modules() {
|
||||
let snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, 0);
|
||||
if snap == INVALID_HANDLE_VALUE {
|
||||
write_log("fifa17: module snapshot FAILED\n");
|
||||
return;
|
||||
}
|
||||
let mut me: MODULEENTRY32W = core::mem::zeroed();
|
||||
me.dwSize = core::mem::size_of::<MODULEENTRY32W>() as u32;
|
||||
if Module32FirstW(snap, &mut me) != 0 {
|
||||
loop {
|
||||
let name = wide_to_string(&me.szModule);
|
||||
let base = me.modBaseAddr as usize;
|
||||
let size = me.modBaseSize;
|
||||
write_log(&format!(
|
||||
"fifa17: module {name:<28} base={base:#018x} size={size:#x}\n"
|
||||
));
|
||||
me.dwSize = core::mem::size_of::<MODULEENTRY32W>() as u32;
|
||||
if Module32NextW(snap, &mut me) == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
write_log("fifa17: Module32FirstW FAILED\n");
|
||||
}
|
||||
CloseHandle(snap);
|
||||
}
|
||||
|
||||
/// Worker that runs AFTER DllMain returns (loader lock released). ToolHelp and
|
||||
/// other loader-touching calls are unsafe under the loader lock, so we defer them
|
||||
/// to this thread. This is what fixed the "game exits right after DllMain" issue.
|
||||
unsafe extern "system" fn worker(_: *mut core::ffi::c_void) -> u32 {
|
||||
write_log("=== fifa17 hook: worker thread start ===\n");
|
||||
let main_base = GetModuleHandleA(core::ptr::null()) as usize;
|
||||
let img = size_of_image(main_base);
|
||||
write_log(&format!(
|
||||
"fifa17: main exe base={main_base:#018x} SizeOfImage={img:#x}\n"
|
||||
));
|
||||
dump_modules();
|
||||
write_log("fifa17: worker complete (injection healthy)\n");
|
||||
// SBC render intervention (inert unless OPENFUT_SBC_HOOK=1). Spawns its own deferred
|
||||
// worker that waits for CardsDLL to load. See sbc_hook.rs / docs/sbc-hook-dll-spec.md.
|
||||
crate::sbc_hook::install();
|
||||
// Passive transaction tracing has a separate kill switch from cache resolution.
|
||||
// It currently fails closed until safe relocating trampolines are proven.
|
||||
crate::sbc_trace::install();
|
||||
crate::sbc_request_trace::install();
|
||||
0
|
||||
}
|
||||
|
||||
/// Minimal FIFA-17 install. Keep DllMain itself trivial: only spawn a worker
|
||||
/// thread and return immediately, so we never touch the loader lock from here.
|
||||
pub unsafe fn install() {
|
||||
use windows_sys::Win32::System::Threading::CreateThread;
|
||||
write_log("=== fifa17 hook: DllMain ATTACH (spawning worker) ===\n");
|
||||
let h = CreateThread(
|
||||
core::ptr::null(),
|
||||
0,
|
||||
Some(worker),
|
||||
core::ptr::null(),
|
||||
0,
|
||||
core::ptr::null_mut(),
|
||||
);
|
||||
if h == 0 as _ {
|
||||
write_log("fifa17: CreateThread FAILED\n");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user