123 lines
No EOL
4.6 KiB
Rust
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");
|
|
} |