wicked-waifus-win-patch/src/extras.rs
2025-01-22 03:37:47 +01:00

123 lines
No EOL
4.6 KiB
Rust

#![cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))]
use std::env::VarError;
use std::ffi::{c_char, CStr, CString};
use std::sync::OnceLock;
use std::thread;
use std::time::Duration;
use ilhook::x64::Registers;
use windows::core::PCSTR;
use windows::Win32::System::LibraryLoader::GetModuleHandleA;
use crate::{config, curl_utils};
use crate::config::{CONFIG, CurlConfig};
use crate::replacer::{AbstractReplacer, GenericReplacer, Replacer};
type CurlEasySetStr = fn(handle: usize, tag: u64, value: *const c_char);
static mut URL_REPLACER: OnceLock<Vec<AbstractReplacer>> = OnceLock::new();
static UE_CURL_EASY_SETOPT_FUNC: OnceLock<usize> = OnceLock::new();
trait EnvBoolMapper {
fn map_env_bool(self, default: bool) -> bool;
}
impl EnvBoolMapper for Result<String, VarError> {
fn map_env_bool(self, default: bool) -> bool {
self.map(|val| match val.as_str() {
"y" => true,
_ => false
}).unwrap_or(default)
}
}
pub(crate) fn configure_extras(interceptor: &mut interceptor_rs::Interceptor) {
unsafe {
URL_REPLACER.set(vec![
// Config Server Replacer
AbstractReplacer::GenericReplacer(GenericReplacer {
regex: regex::Regex::new(CONFIG.replacement_config.config_server_regex).unwrap(),
replacement: std::env::var("CFG_SERVER_URL")
.unwrap_or(config::CONFIG_SERVER_DEFAULT.to_string()),
force_http: std::env::var("CFG_SERVER_FORCE_HTTP").map_env_bool(true),
}),
// TODO: Hotpatch Server replacer
// Log server replacer
AbstractReplacer::GenericReplacer(GenericReplacer {
regex: regex::Regex::new(CONFIG.replacement_config.log_server_regex).unwrap(),
replacement: std::env::var("LOG_SERVER_URL")
.unwrap_or(config::LOG_SERVER_DEFAULT.to_string()),
force_http: std::env::var("LOG_SERVER_FORCE_HTTP").map_env_bool(true),
}),
// TODO: SDK Server replacer
]).unwrap()
}
let module = unsafe { GetModuleHandleA(PCSTR::null()) }.unwrap();
println!("Game base: {:X}", module.0 as usize);
let _ = UE_CURL_EASY_SETOPT_FUNC.set(module.0 as usize + CONFIG.ue_curl_config.curl_easy_setopt);
interceptor
.attach(
(module.0 as usize) + CONFIG.ue_curl_config.curl_easy_perform,
on_curl_easy_perform,
Some(&CONFIG.ue_curl_config as *const _ as usize)
).unwrap();
let krsdk_ex = loop {
match unsafe { GetModuleHandleA(CONFIG.disable_sdk.sdk_dll) } {
Ok(handle) => break handle,
Err(_) => thread::sleep(Duration::from_millis(1)),
}
};
interceptor
.replace((krsdk_ex.0 as usize) + CONFIG.disable_sdk.eula_accept, dummy, None)
.unwrap();
interceptor
.replace((krsdk_ex.0 as usize) + CONFIG.disable_sdk.sdk_go_away, dummy, None)
.unwrap();
}
unsafe extern "win64" fn dummy(_: *mut Registers, _: usize, _: usize) -> usize {
1
}
unsafe extern "win64" fn on_curl_easy_perform(reg: *mut Registers, user_data: usize) {
let config = std::ptr::read(user_data as *const CurlConfig);
let curl_handle = unsafe {
*(((*reg).rcx + config.handle_rcx_relative_offset) as *const usize)
};
let url_ptr = unsafe {
*((curl_handle + config.url_handle_relative_offset) as *const usize)
};
let url = unsafe { CStr::from_ptr(url_ptr as *const i8) }.to_str().unwrap();
println!("[curl_easy_perform] Original URL: {url}");
for replacer in unsafe { URL_REPLACER.get_mut().unwrap() } {
match replacer.replace(url) {
Ok(result) => {
println!("[curl_easy_perform] Replacement URL: {result}");
let url = CString::new(result.as_str()).unwrap();
unsafe {
// TODO: Rethink this for other curl interceptors
std::mem::transmute::<usize, CurlEasySetStr>(*UE_CURL_EASY_SETOPT_FUNC.get().unwrap())(
curl_handle,
curl_utils::CURL_OPT_URL,
url.as_ptr(),
)
}
// TODO: Future stuff
// let headers_ptr = unsafe { *(((*reg).rcx + 0x118) as *const usize) };
// let headers = unsafe { std::slice::from_raw_parts(*(headers_ptr as *const usize) as *const u8, 1000) };
// println!("Headers: {headers:02X?}");
return;
}
Err(_) => {}
};
};
println!("No valid url match found");
}