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:
+80
-20
@@ -1,6 +1,11 @@
|
||||
mod config;
|
||||
mod connect_hook;
|
||||
mod connectex_hook;
|
||||
mod hooks;
|
||||
mod iat;
|
||||
mod origin_spy;
|
||||
mod ssl_patch;
|
||||
mod tls_bypass;
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::{BOOL, HMODULE, TRUE},
|
||||
@@ -8,35 +13,90 @@ use windows_sys::Win32::{
|
||||
Networking::WinSock::ADDRINFOA,
|
||||
};
|
||||
|
||||
pub(crate) fn write_log(msg: &str) {
|
||||
use std::io::Write;
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new()
|
||||
.create(true).append(true)
|
||||
.open(r"C:\openfut_hook.log")
|
||||
{ let _ = f.write_all(msg.as_bytes()); }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "system" fn DllMain(
|
||||
module: HMODULE,
|
||||
reason: u32,
|
||||
_reserved: *mut (),
|
||||
) -> BOOL {
|
||||
if reason == DLL_PROCESS_ATTACH {
|
||||
install_hooks(module);
|
||||
}
|
||||
pub unsafe extern "system" fn DllMain(module: HMODULE, reason: u32, _: *mut ()) -> BOOL {
|
||||
if reason == DLL_PROCESS_ATTACH { install_hooks(module); }
|
||||
TRUE
|
||||
}
|
||||
|
||||
unsafe fn install_hooks(module: HMODULE) {
|
||||
// Load redirect IP from openfut.cfg before patching
|
||||
write_log("openfut_hook: DllMain fired\n");
|
||||
let ip = config::read_redirect_ip(module);
|
||||
hooks::set_redirect_ip(ip);
|
||||
|
||||
let real_ptr = iat::resolve(b"ws2_32.dll\0", b"getaddrinfo\0");
|
||||
if real_ptr.is_null() {
|
||||
return;
|
||||
let ga = iat::resolve(b"ws2_32.dll\0", b"getaddrinfo\0");
|
||||
if !ga.is_null() {
|
||||
let f: unsafe extern "system" fn(*const u8,*const u8,*const ADDRINFOA,*mut *mut ADDRINFOA)->i32
|
||||
= std::mem::transmute(ga);
|
||||
hooks::set_real(f);
|
||||
let n = iat::patch_iat(ga, hooks::hooked_getaddrinfo as *const ());
|
||||
let m = iat::patch_iat_in(b"EAWebKit.dll\0", ga, hooks::hooked_getaddrinfo as *const ());
|
||||
write_log(&format!("openfut_hook: getaddrinfo IAT patched {n}+{m}\n"));
|
||||
}
|
||||
|
||||
let real_fn: unsafe extern "system" fn(
|
||||
*const u8,
|
||||
*const u8,
|
||||
*const ADDRINFOA,
|
||||
*mut *mut ADDRINFOA,
|
||||
) -> i32 = std::mem::transmute(real_ptr);
|
||||
if ssl_patch::patch_main_exe_cert_verify() { write_log("ssl: main exe cert-verify patched\n"); }
|
||||
else { write_log("ssl: main exe cert-verify NOT FOUND\n"); }
|
||||
if ssl_patch::patch_eawebkit_cert_verify() { write_log("ssl: EAWebKit cert-verify patched\n"); }
|
||||
else { write_log("ssl: EAWebKit cert-verify deferred\n"); }
|
||||
|
||||
hooks::set_real(real_fn);
|
||||
iat::patch_iat(real_ptr, hooks::hooked_getaddrinfo as *const ());
|
||||
if connect_hook::install_inline_connect_hook() { write_log("connect: inline-hooked\n"); }
|
||||
else { write_log("connect: hook FAILED\n"); }
|
||||
let wp = iat::resolve(b"ws2_32.dll\0", b"WSAConnect\0");
|
||||
if !wp.is_null() {
|
||||
let f: unsafe extern "system" fn(usize,*const u8,i32,*const(),*const(),*const(),*const())->i32
|
||||
= std::mem::transmute(wp);
|
||||
connect_hook::set_real_wsa_connect(f);
|
||||
iat::patch_iat(wp, connect_hook::hooked_wsa_connect as *const ());
|
||||
write_log("connect: WSAConnect IAT patched\n");
|
||||
}
|
||||
|
||||
if connectex_hook::install_wsaioctl_hook() { write_log("connectex: WSAIoctl inline-hooked\n"); }
|
||||
else { write_log("connectex: WSAIoctl hook FAILED\n"); }
|
||||
|
||||
// recv/send hooks removed — LSX is now handled by the native openfut-bridge
|
||||
// LSX server (port 3216), so in-process interception is no longer needed.
|
||||
|
||||
macro_rules! hook_iat {
|
||||
($dll:expr, $sym:expr, $setter:ident, $handler:expr, $ty:ty) => {{
|
||||
let ptr = iat::resolve($dll, $sym);
|
||||
if !ptr.is_null() {
|
||||
let f: $ty = std::mem::transmute(ptr);
|
||||
origin_spy::$setter(f);
|
||||
iat::patch_iat(ptr, $handler as *const ());
|
||||
"ok"
|
||||
} else { "miss" }
|
||||
}};
|
||||
}
|
||||
let ra = hook_iat!(b"advapi32.dll\0", b"RegQueryValueExA\0", set_real_reg_a,
|
||||
origin_spy::hooked_reg_query_a,
|
||||
unsafe extern "system" fn(isize,*const u8,*mut u32,*mut u32,*mut u8,*mut u32)->i32);
|
||||
let rw = hook_iat!(b"advapi32.dll\0", b"RegQueryValueExW\0", set_real_reg_w,
|
||||
origin_spy::hooked_reg_query_w,
|
||||
unsafe extern "system" fn(isize,*const u16,*mut u32,*mut u32,*mut u8,*mut u32)->i32);
|
||||
let ma = hook_iat!(b"kernel32.dll\0", b"OpenMutexA\0", set_real_mutex_a,
|
||||
origin_spy::hooked_open_mutex_a,
|
||||
unsafe extern "system" fn(u32,i32,*const u8)->isize);
|
||||
let mw = hook_iat!(b"kernel32.dll\0", b"OpenMutexW\0", set_real_mutex_w,
|
||||
origin_spy::hooked_open_mutex_w,
|
||||
unsafe extern "system" fn(u32,i32,*const u16)->isize);
|
||||
write_log(&format!("origin_spy: RegA={ra} RegW={rw} MutexA={ma} MutexW={mw}\n"));
|
||||
|
||||
let cv = iat::resolve(b"crypt32.dll\0", b"CertVerifyCertificateChainPolicy\0");
|
||||
if !cv.is_null() {
|
||||
let f: unsafe extern "system" fn(*const u8,*const(),*const(),*mut u32)->BOOL
|
||||
= std::mem::transmute(cv);
|
||||
tls_bypass::set_real(f);
|
||||
iat::patch_iat(cv, tls_bypass::hooked_cert_verify_chain_policy as *const ());
|
||||
iat::patch_iat_in(b"EAWebKit.dll\0", cv, tls_bypass::hooked_cert_verify_chain_policy as *const ());
|
||||
iat::patch_iat_in(b"winhttp.dll\0", cv, tls_bypass::hooked_cert_verify_chain_policy as *const ());
|
||||
iat::patch_iat_in(b"wininet.dll\0", cv, tls_bypass::hooked_cert_verify_chain_policy as *const ());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user