d1a71bd5a1
Modernize manual nul-terminated byte strings to C-string literals (c"...") at all Win32 GetModuleHandleA/GetProcAddress/getaddrinfo call sites (byte-identical), drop two redundant SOL_SOCKET-as-i32 casts, remove a needless return in the fifa17 install path, and add a # Safety section to DllMain. Scope the FIFA-23-path dead-code/unused-import lints (unused only under the fifa17 feature, stripped by the linker) with a documented crate-level cfg_attr allow. Cross-verified: both the default and fifa17 builds now pass clippy -D warnings and compile; probe and capture_baseline still build.
82 lines
3.1 KiB
Rust
82 lines
3.1 KiB
Rust
// Runtime in-memory patch for ProtoSSL's certificate verification function inside
|
|
// EAWebKit.dll. Rather than patching the DLL on disk (offset-dependent, fragile),
|
|
// we scan the loaded module for the function's unique byte prologue and overwrite the
|
|
// first six bytes with `mov eax, 1; ret` — making every cert-chain validation call
|
|
// immediately return success.
|
|
//
|
|
// Why this is safe: the patched function (`ProtoSSL_VerifyCert` at VA 0x180a85570 in
|
|
// the shipped binary) is only used by ProtoSSL's TLS state machine to validate the
|
|
// server's certificate chain. Always returning 1 is equivalent to trusting all certs,
|
|
// which is the behaviour we want for the local self-signed bridge certificate.
|
|
|
|
use windows_sys::Win32::System::{
|
|
LibraryLoader::GetModuleHandleA,
|
|
Memory::{VirtualProtect, PAGE_EXECUTE_READWRITE},
|
|
};
|
|
|
|
// Unique 22-byte prologue of ProtoSSL's cert-verify function.
|
|
// Confirmed present in the EA-shipped EAWebKit.dll (June 2023 build).
|
|
const PROLOGUE: &[u8] = &[
|
|
0x44, 0x89, 0x44, 0x24, 0x18, // mov [rsp+0x18], r8d
|
|
0x48, 0x89, 0x54, 0x24, 0x10, // mov [rsp+0x10], rdx
|
|
0x56, // push rsi
|
|
0x57, // push rdi
|
|
0x41, 0x55, // push r13
|
|
0x41, 0x56, // push r14
|
|
0x41, 0x57, // push r15
|
|
0x48, 0x83, 0xec, 0x30, // sub rsp, 0x30
|
|
];
|
|
|
|
// Return 0 (PROTOSSL_ERROR_NONE = success). ProtoSSL convention: 0 = ok, negative = error.
|
|
// The function sets r15d = 0xFFFFFFFF (-1) for its own error returns, confirming 0 = success.
|
|
const PATCH: &[u8] = &[
|
|
0x31, 0xc0, // xor eax, eax (eax = 0 = PROTOSSL_ERROR_NONE)
|
|
0xc3, // ret
|
|
0x90, 0x90, 0x90, // nop padding
|
|
];
|
|
|
|
fn patch_module(module: isize, scan_bytes: usize) -> bool {
|
|
if module == 0 {
|
|
return false;
|
|
}
|
|
let base = module as usize;
|
|
let image: &[u8] = unsafe { core::slice::from_raw_parts(base as *const u8, scan_bytes) };
|
|
let offset = match image.windows(PROLOGUE.len()).position(|w| w == PROLOGUE) {
|
|
Some(o) => o,
|
|
None => return false,
|
|
};
|
|
let target = (base + offset) as *mut u8;
|
|
let mut old_prot: u32 = 0;
|
|
unsafe {
|
|
VirtualProtect(
|
|
target as *const core::ffi::c_void,
|
|
PATCH.len(),
|
|
PAGE_EXECUTE_READWRITE,
|
|
&mut old_prot,
|
|
);
|
|
core::ptr::copy_nonoverlapping(PATCH.as_ptr(), target, PATCH.len());
|
|
VirtualProtect(
|
|
target as *const core::ffi::c_void,
|
|
PATCH.len(),
|
|
old_prot,
|
|
&mut old_prot,
|
|
);
|
|
}
|
|
true
|
|
}
|
|
|
|
/// Patch ProtoSSL cert-verify in EAWebKit.dll (call when EAWebKit is loaded).
|
|
pub unsafe fn patch_eawebkit_cert_verify() -> bool {
|
|
let module = GetModuleHandleA(c"EAWebKit.dll".as_ptr().cast()) as isize;
|
|
// EAWebKit.dll is ~22 MB
|
|
patch_module(module, 24 * 1024 * 1024)
|
|
}
|
|
|
|
/// Patch ProtoSSL cert-verify compiled into FIFA23.exe itself (DirtySDK's copy).
|
|
/// The main exe is ~100 MB; confirmed present at file offset 0xf0c850.
|
|
pub unsafe fn patch_main_exe_cert_verify() -> bool {
|
|
let module = GetModuleHandleA(core::ptr::null()) as isize;
|
|
// Scan first 110 MB — the function is near offset 0xf0c850 (~15 MB in)
|
|
patch_module(module, 110 * 1024 * 1024)
|
|
}
|