feat(hook): expand IAT hook coverage with TLS bypass, connect/recv hooks, and logging
Adds connect_hook, connectex_hook, recv_hook, ssl_patch, tls_bypass, lsx, ea_stub, and origin_spy modules to intercept EA's TLS and socket layers in addition to getaddrinfo. Adds DLL-level logging to C:\openfut_hook.log for debugging. Also patches windows-sys feature flags to include Cryptography and Threading APIs needed by the new hooks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// 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(b"EAWebKit.dll\0".as_ptr()) 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)
|
||||
}
|
||||
Reference in New Issue
Block a user