From 2b2a11df4c682f70664b33d9d0ec64cfc92a9a43 Mon Sep 17 00:00:00 2001 From: xavo95 Date: Fri, 16 May 2025 10:51:56 +0000 Subject: [PATCH] 2.4.0 (#7) Reviewed-on: https://git.xeondev.com/WutheringSlaves/wicked-waifus-win-patch/pulls/7 --- Cargo.lock | 66 ++++++++++++++++++---- Cargo.toml | 11 ++-- archive.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++ src/config.rs | 111 ++++++++++++++++++------------------- src/curl_hook.rs | 93 +++++++++++++++++++++++++++++++ src/curl_utils.rs | 26 --------- src/extras.rs | 123 ----------------------------------------- src/lib.rs | 61 +++++++++++++++------ src/replacer.rs | 83 ---------------------------- src/sdk.rs | 38 +++++++++++++ 10 files changed, 423 insertions(+), 326 deletions(-) create mode 100644 src/curl_hook.rs delete mode 100644 src/curl_utils.rs delete mode 100644 src/extras.rs delete mode 100644 src/replacer.rs create mode 100644 src/sdk.rs diff --git a/Cargo.lock b/Cargo.lock index 9b2ecd1..0f36a7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,19 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "curly-injector" +version = "0.1.0" +source = "git+https://git.xeondev.com/ReversedRoomsMisc/curly-injector.git#1184af99d3788931ee691f5922c55d9ea06b3003" +dependencies = [ + "ilhook", + "interceptor-rs", + "regex", +] [[package]] name = "iced-x86" @@ -37,14 +47,23 @@ dependencies = [ "lazy_static", "libc", "regex", - "thiserror", + "thiserror 1.0.69", "windows-sys", ] +[[package]] +name = "injector-utils" +version = "0.1.0" +source = "git+https://git.xeondev.com/ReversedRoomsMisc/process-launcher-rs.git#4dc7349c86020b92d795f74a30c9f3c76414f2f4" +dependencies = [ + "thiserror 2.0.12", + "windows", +] + [[package]] name = "interceptor-rs" version = "0.1.0" -source = "git+https://git.xeondev.com/xavo95/interceptor-rs.git#418aef083cc6768201f0512fdbdca5c03aa4f787" +source = "git+https://git.xeondev.com/ReversedRoomsMisc/interceptor-rs.git#418aef083cc6768201f0512fdbdca5c03aa4f787" dependencies = [ "ilhook", ] @@ -57,9 +76,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "memchr" @@ -69,9 +88,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -116,9 +135,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -131,7 +150,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -145,6 +173,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.18" @@ -154,8 +193,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unreal-niggery-rs" version = "0.1.0" -source = "git+https://git.xeondev.com/xavo95/unreal-niggery-rs.git#07330a27e1e49f0544f5fde51698c0a2300cc737" +source = "git+https://git.xeondev.com/ReversedRoomsMisc/unreal-niggery-rs.git#e07eda21e461e1ec234ec9ef2562dc8187742631" dependencies = [ + "thiserror 2.0.12", "widestring", ] @@ -163,7 +203,9 @@ dependencies = [ name = "wicked-waifus-win-patch" version = "0.1.0" dependencies = [ + "curly-injector", "ilhook", + "injector-utils", "interceptor-rs", "regex", "unreal-niggery-rs", diff --git a/Cargo.toml b/Cargo.toml index c431cf6..8802276 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wicked-waifus-win-patch" version = "0.1.0" -edition = "2021" +edition = "2024" [lib] name = "wicked_waifus_win" @@ -9,17 +9,18 @@ crate-type = ["cdylib"] [features] advanced = [] -cn_beta_2_3_0 = [] -os_live_2_2_0 = [] +cn_beta_2_4_0 = [] enable-sdk = [] only-sig-bypass = [] regular = ["dep:regex", "dep:widestring"] [dependencies] +curly-injector = { git = "https://git.xeondev.com/ReversedRoomsMisc/curly-injector.git" } ilhook = "2.1.1" -interceptor-rs = { git = "https://git.xeondev.com/xavo95/interceptor-rs.git" } +injector-utils = { git = "https://git.xeondev.com/ReversedRoomsMisc/process-launcher-rs.git" } +interceptor-rs = { git = "https://git.xeondev.com/ReversedRoomsMisc/interceptor-rs.git" } regex = { version = "1.11.1", optional = true } -unreal-niggery-rs = { git = "https://git.xeondev.com/xavo95/unreal-niggery-rs.git" } +unreal-niggery-rs = { git = "https://git.xeondev.com/ReversedRoomsMisc/unreal-niggery-rs.git" } widestring = { version = "1.2.0", optional = true } windows = { version = "0.61.1", features = [ "Win32_Foundation", diff --git a/archive.md b/archive.md index e32c159..7562eca 100644 --- a/archive.md +++ b/archive.md @@ -1,3 +1,140 @@ +# CN BETA 2.3.0 +```rust +#[cfg(feature = "cn_beta_2_3_0")] +pub(crate) const CONFIG: InjectConfiguration = InjectConfiguration { + f_pak_file_check: 0x4274440, + f_pak_file_check_preamble: 0x8D48574157565540, + resize_grow: 0x8E2D30, + f_print_f: 0x28E5F70, + add_pak_folders_entry: 0x427B910, + add_pak_folders_ret: 0x427E1B0, + #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] + ue_curl_config: CurlConfig { + handle_rcx_relative_offset: 0x110, + url_handle_relative_offset: 0x880, + http_headers_handle_relative_offset: None, + curl_easy_setopt: 0x66325A0, + curl_easy_perform: 0x3C0BFA0, + }, + #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] + replacement_config: ReplacementConfig { + config_server_regex: r#"^(https|http)://.*/([a-zA-Z0-9]{32}/index\.json)$"#, + // hotpatch_server_regex: "", + log_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, + sdk_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, + replacement_defaults: &ReplacementDefaults { + config_server_default: "127.0.0.1:10001", + // hotpatch_server_default: "127.0.0.1:10001", + log_server_default: "127.0.0.1:10001", + sdk_server_default: "127.0.0.1:10001", + }, + }, + #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] + disable_sdk: DisableSdkConfiguration { + sdk_dll: s!("KRSDKEx.dll"), + eula_accept: 0x4F410, + sdk_go_away: 0x93620, + }, + #[cfg(all(feature = "enable-sdk", not(feature = "only-sig-bypass"), feature = "regular"))] + kr_curl: KrCurlConfiguration { + curl_dll: s!("libkrsdkcurl.dll"), + curl_config: CurlConfig { + handle_rcx_relative_offset: 0, + url_handle_relative_offset: 0x1220, + http_headers_handle_relative_offset: Some(0x340), + curl_easy_setopt: 0x36E50, + curl_easy_perform: 0xE3D0, + }, + } +}; +``` + +# OS LIVE 2.2.0 +```rust +#[cfg(feature = "os_live_2_2_0")] +pub(crate) const CONFIG: InjectConfiguration = InjectConfiguration { + f_pak_file_check: 0x418A2F0, + f_pak_file_check_preamble: 0x8D48574157565540, + resize_grow: 0x08D6D70, + f_print_f: 0x280B240, + add_pak_folders_entry: 0x41917D0, + add_pak_folders_ret: 0x4194070, + #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] + ue_curl_config: CurlConfig { + handle_rcx_relative_offset: Some(0x110), + url_handle_relative_offset: 0x880, + http_headers_handle_relative_offset: None, + curl_easy_setopt: 0x64FF840, + curl_easy_perform: 0x3B21490, + }, + #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] + replacement_config: ReplacementConfig { + config_server_regex: r#"^(https|http)://.*/([a-zA-Z0-9]{32}/index\.json)$"#, + // hotpatch_server_regex: "", + log_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, + // sdk_server_regex: "", + // replacement_defaults: &ReplacementDefaults { + // config_server_default: "127.0.0.1:10001", + // // hotpatch_server_default: "127.0.0.1:10001", + // log_server_default: "127.0.0.1:10001", + // sdk_server_default: "127.0.0.1:10001", + // }, + }, + #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] + disable_sdk: DisableSdkConfiguration { + sdk_dll: s!("KRSDK.dll"), + eula_accept: 0x96800, + sdk_go_away: 0xA2680, + }, + // TODO: Ported for compliance in the future, not supported on 2.2.0 OS + #[cfg(all(feature = "enable-sdk", not(feature = "only-sig-bypass"), feature = "regular"))] + kr_curl: KrCurlConfiguration { + curl_dll: s!("libkrsdkcurl.dll"), + curl_config: CurlConfig { + handle_rcx_relative_offset: None, + url_handle_relative_offset: 0, + http_headers_handle_relative_offset: None, + curl_easy_setopt: 0, + curl_easy_perform: 0, + }, + } +}; +``` + +# CN BETA 2.2.1 + +```rust +#[cfg(feature = "cn_beta_2_2_1")] +pub(crate) const CONFIG: InjectConfiguration = InjectConfiguration { + f_pak_file_check: 0x41CE7F0, + f_pak_file_check_preamble: 0x8D48574157565540, + resize_grow: 0x08D9510, + f_print_f: 0x2852CE0, + add_pak_folders_entry: 0x41D5CD0, + add_pak_folders_ret: 0x41D8570, + #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] + ue_curl_config: CurlConfig { + handle_rcx_relative_offset: 0x110, + url_handle_relative_offset: 0x880, + curl_easy_setopt: 0x657A660, + curl_easy_perform: 0x3B6A440, + }, + #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] + replacement_config: ReplacementConfig { + config_server_regex: r#"^(https|http)://.*/([a-zA-Z0-9]{32}/index\.json)$"#, + // hotpatch_server_regex: "", + log_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, + // sdk_server_regex: "", + }, + #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] + disable_sdk: DisableSdkConfiguration { + sdk_dll: s!("KRSDKEx.dll"), + eula_accept: 0x4ED80, + sdk_go_away: 0x91FE0, + }, +}; +``` + # OS LIVE 2.1.0 ```rust diff --git a/src/config.rs b/src/config.rs index 2f7fbb6..4cb4eb3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,14 +1,15 @@ -#[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] +#[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] use windows::core::{PCSTR, s}; +use curly_injector::CurlConfig; -#[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] -pub(crate) const CONFIG_SERVER_DEFAULT: &'static str = "127.0.0.1:10001"; -#[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] -// pub(crate) const HOTPATCH_SERVER_DEFAULT: &'static str = "127.0.0.1:10001"; -#[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] -pub(crate) const LOG_SERVER_DEFAULT: &'static str = "127.0.0.1:10001"; -#[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] -// pub(crate) const SDK_SERVER_DEFAULT: &'static str = "127.0.0.1:10001"; +#[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] +pub(crate) struct ReplacementDefaults { + pub(crate) config_server_default: &'static str, + // pub(crate) hotpatch_server_default: &'static str, + pub(crate) log_server_default: &'static str, + #[cfg(feature = "enable-sdk")] + pub(crate) sdk_server_default: &'static str, +} #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] pub(crate) struct DisableSdkConfiguration { @@ -17,20 +18,20 @@ pub(crate) struct DisableSdkConfiguration { pub(crate) sdk_go_away: usize, } -#[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] -pub(crate) struct CurlConfig { - pub(crate) handle_rcx_relative_offset: u64, - pub(crate) url_handle_relative_offset: usize, - pub(crate) curl_easy_setopt: usize, - pub(crate) curl_easy_perform: usize, -} - #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] pub(crate) struct ReplacementConfig { pub(crate) config_server_regex: &'static str, // pub(crate) hotpatch_server_regex: &'static str, pub(crate) log_server_regex: &'static str, - // pub(crate) sdk_server_regex: &'static str, + #[cfg(feature = "enable-sdk")] + pub(crate) sdk_server_regex: &'static str, + pub(crate) replacement_defaults: &'static ReplacementDefaults, +} + +#[cfg(all(feature = "enable-sdk", not(feature = "only-sig-bypass"), feature = "regular"))] +pub(crate) struct KrCurlConfiguration { + pub(crate) curl_dll: PCSTR, + pub(crate) curl_config: CurlConfig, } pub(crate) struct InjectConfiguration { @@ -46,64 +47,56 @@ pub(crate) struct InjectConfiguration { pub(crate) replacement_config: ReplacementConfig, #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] pub(crate) disable_sdk: DisableSdkConfiguration, + #[cfg(all(feature = "enable-sdk", not(feature = "only-sig-bypass"), feature = "regular"))] + pub(crate) kr_curl: KrCurlConfiguration, } -#[cfg(feature = "cn_beta_2_3_0")] +#[cfg(feature = "cn_beta_2_4_0")] pub(crate) const CONFIG: InjectConfiguration = InjectConfiguration { - f_pak_file_check: 0x4274440, + f_pak_file_check: 0x42CF240, f_pak_file_check_preamble: 0x8D48574157565540, - resize_grow: 0x8E2D30, - f_print_f: 0x28E5F70, - add_pak_folders_entry: 0x427B910, - add_pak_folders_ret: 0x427E1B0, + resize_grow: 0x08E1690, + f_print_f: 0x2912CF0, + add_pak_folders_entry: 0x42D6720, + add_pak_folders_ret: 0x42D8FC0, #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] ue_curl_config: CurlConfig { handle_rcx_relative_offset: 0x110, url_handle_relative_offset: 0x880, - curl_easy_setopt: 0x66325A0, - curl_easy_perform: 0x3C0BFA0, + http_headers_handle_relative_offset: None, + curl_easy_setopt: 0x66B3720, + curl_easy_perform: 0x3C65C60, }, #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] replacement_config: ReplacementConfig { config_server_regex: r#"^(https|http)://.*/([a-zA-Z0-9]{32}/index\.json)$"#, // hotpatch_server_regex: "", log_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, - // sdk_server_regex: "", + #[cfg(feature = "enable-sdk")] + sdk_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, + replacement_defaults: &ReplacementDefaults { + config_server_default: "127.0.0.1:10001", + // hotpatch_server_default: "127.0.0.1:10001", + log_server_default: "127.0.0.1:10001", + #[cfg(feature = "enable-sdk")] + sdk_server_default: "127.0.0.1:10001", + }, }, #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] disable_sdk: DisableSdkConfiguration { sdk_dll: s!("KRSDKEx.dll"), - eula_accept: 0x4F410, - sdk_go_away: 0x93620, - }, -}; - -#[cfg(feature = "os_live_2_2_0")] -pub(crate) const CONFIG: InjectConfiguration = InjectConfiguration { - f_pak_file_check: 0x418A2F0, - f_pak_file_check_preamble: 0x8D48574157565540, - resize_grow: 0x08D6D70, - f_print_f: 0x280B240, - add_pak_folders_entry: 0x41917D0, - add_pak_folders_ret: 0x4194070, - #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] - ue_curl_config: CurlConfig { - handle_rcx_relative_offset: 0x110, - url_handle_relative_offset: 0x880, - curl_easy_setopt: 0x64FF840, - curl_easy_perform: 0x3B21490, - }, - #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] - replacement_config: ReplacementConfig { - config_server_regex: r#"^(https|http)://.*/([a-zA-Z0-9]{32}/index\.json)$"#, - // hotpatch_server_regex: "", - log_server_regex: r#"^(https|http)://.*\.cos\..*\.myqcloud\.com/(.*)$"#, - // sdk_server_regex: "", - }, - #[cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] - disable_sdk: DisableSdkConfiguration { - sdk_dll: s!("KRSDK.dll"), - eula_accept: 0x96800, - sdk_go_away: 0xA2680, + eula_accept: 0x4F490, + sdk_go_away: 0x93FD0, }, + #[cfg(all(feature = "enable-sdk", not(feature = "only-sig-bypass"), feature = "regular"))] + kr_curl: KrCurlConfiguration { + curl_dll: s!("libkrsdkcurl.dll"), + curl_config: CurlConfig { + handle_rcx_relative_offset: 0, + url_handle_relative_offset: 0x1220, + http_headers_handle_relative_offset: Some(0x340), + curl_easy_setopt: 0x36E50, + curl_easy_perform: 0xE3D0, + }, + } }; \ No newline at end of file diff --git a/src/curl_hook.rs b/src/curl_hook.rs new file mode 100644 index 0000000..20e02b4 --- /dev/null +++ b/src/curl_hook.rs @@ -0,0 +1,93 @@ +// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + +use crate::config::ReplacementConfig; +use curly_injector::replacer::AbstractReplacer; +use curly_injector::utils::EnvBoolMapper; +use curly_injector::{CurlConfig, CurlUserData}; +use std::sync::OnceLock; +use windows::core::PCSTR; + +static mut UE_CURL_EASY: OnceLock = OnceLock::new(); +#[cfg(feature = "enable-sdk")] +static mut KR_CURL_EASY: OnceLock = OnceLock::new(); + +pub(crate) fn configure_ue_curl( + interceptor: &mut interceptor_rs::Interceptor, + module_name: Option, + config: &'static CurlConfig, + replacement: &ReplacementConfig, +) { + let module = injector_utils::get_module_base(module_name); + let replacer = vec![ + // Config Server Replacer + AbstractReplacer::GenericReplacer(curly_injector::replacer::GenericReplacer { + regex: regex::Regex::new(replacement.config_server_regex).unwrap(), + replacement: std::env::var("CFG_SERVER_URL").unwrap_or( + replacement + .replacement_defaults + .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(curly_injector::replacer::GenericReplacer { + regex: regex::Regex::new(replacement.log_server_regex).unwrap(), + replacement: std::env::var("LOG_SERVER_URL").unwrap_or( + replacement + .replacement_defaults + .log_server_default + .to_string(), + ), + force_http: std::env::var("LOG_SERVER_FORCE_HTTP").map_env_bool(true), + }), + ]; + unsafe { + curly_injector::hook_curl( + interceptor, + module.0 as usize, + config, + replacer, + None, + &UE_CURL_EASY, + ); + } +} + +// Not sig bypass and regular check already done at top of the file +#[cfg(feature = "enable-sdk")] +pub(crate) fn configure_kr_curl( + interceptor: &mut interceptor_rs::Interceptor, + module_name: Option, + config: &'static CurlConfig, + replacement: &ReplacementConfig, +) { + let module = injector_utils::get_module_base(module_name); + let replacer = vec![ + // SDK server replacer + AbstractReplacer::GenericReplacer(curly_injector::replacer::GenericReplacer { + regex: regex::Regex::new(replacement.sdk_server_regex).unwrap(), + replacement: std::env::var("SDK_SERVER_URL").unwrap_or( + replacement + .replacement_defaults + .sdk_server_default + .to_string(), + ), + force_http: std::env::var("SDK_SERVER_FORCE_HTTP").map_env_bool(true), + }), + ]; + let proxy_config = Some(ProxyConfig { + proxy_url: "http://127.0.0.1:8888", + skip_url_replace: true, + }); + curly_injector::hook_curl( + interceptor, + module.0 as usize, + config, + replacer, + proxy_config, + &KR_CURL_EASY, + ); +} diff --git a/src/curl_utils.rs b/src/curl_utils.rs deleted file mode 100644 index 85d3e3f..0000000 --- a/src/curl_utils.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] -#![allow(unused)] - -const CURL_OPT_TYPE_LONG: u64 = 0; -const CURL_OPT_TYPE_OBJECT_POINT: u64 = 10000; -const CURL_OPT_TYPE_FUNCTION_POINT: u64 = 20000; -const CURL_OPT_TYPE_OFF_T: u64 = 30000; -const CURL_OPT_TYPE_BLOB: u64 = 40000; - -const CURL_OPT_TYPE_STRING_POINT: u64 = CURL_OPT_TYPE_OBJECT_POINT; -const CURL_OPT_TYPE_S_LIST_POINT: u64 = CURL_OPT_TYPE_OBJECT_POINT; -const CURL_OPT_TYPE_CB_POINT: u64 = CURL_OPT_TYPE_OBJECT_POINT; -const CURL_OPT_TYPE_VALUES: u64 = CURL_OPT_TYPE_LONG; - -#[macro_export] -macro_rules! curl_opt { - ($name:ident, $typ:ident, $value:literal) => { - pub(crate) const $name: u64 = $typ + $value; - }; -} - -curl_opt!(CURL_OPT_URL, CURL_OPT_TYPE_STRING_POINT, 2); -curl_opt!(CURL_OPT_SSL_VERIFY_PEER, CURL_OPT_TYPE_LONG, 64); -curl_opt!(CURL_OPT_CA_INFO, CURL_OPT_TYPE_STRING_POINT, 65); -curl_opt!(CURL_OPT_SSL_VERIFY_HOST, CURL_OPT_TYPE_LONG, 81); -curl_opt!(CURL_OPT_CA_PATH, CURL_OPT_TYPE_STRING_POINT, 97); \ No newline at end of file diff --git a/src/extras.rs b/src/extras.rs deleted file mode 100644 index eedf9ba..0000000 --- a/src/extras.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![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> = OnceLock::new(); -static UE_CURL_EASY_SETOPT_FUNC: OnceLock = OnceLock::new(); - -trait EnvBoolMapper { - fn map_env_bool(self, default: bool) -> bool; -} - -impl EnvBoolMapper for Result { - 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::(*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"); -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6ee7ca3..bac2fca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,9 @@ use std::time::Duration; use unreal_niggery_rs::f_string::{FString, Printf}; use unreal_niggery_rs::t_array::TArray; use unreal_niggery_rs::Add; -use windows::core::{PCSTR, PCWSTR}; +use windows::core::PCSTR; +#[cfg(any(feature = "only-sig-bypass", feature = "regular"))] +use windows::core::PCWSTR; use windows::Win32::Foundation::HINSTANCE; use windows::Win32::System::Console; use windows::Win32::System::LibraryLoader::GetModuleHandleA; @@ -16,11 +18,9 @@ use config::CONFIG; mod config; #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] -mod curl_utils; +mod curl_hook; #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] -mod extras; -#[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] -mod replacer; +mod sdk; static CUSTOM_PAK_FOLDER: OnceLock = OnceLock::new(); @@ -41,6 +41,7 @@ fn thread_func() { } let mut interceptor = Interceptor::new(); + #[cfg(any(feature = "only-sig-bypass", feature = "regular"))] interceptor .replace( (module.0 as usize) + CONFIG.f_pak_file_check, @@ -71,11 +72,7 @@ fn thread_func() { .unwrap(); } - #[cfg(all( - not(feature = "only-sig-bypass"), - feature = "regular", - feature = "advanced" - ))] + #[cfg(feature = "advanced")] wicked_waifus_win_payload_advanced::enable_advanced_features( module.0 as usize, &mut interceptor, @@ -90,39 +87,67 @@ fn thread_func() { ); #[cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] - extras::configure_extras(&mut interceptor); + curl_hook::configure_ue_curl( + &mut interceptor, + None, + &CONFIG.ue_curl_config, + &CONFIG.replacement_config, + ); + #[cfg(all( + not(feature = "enable-sdk"), + not(feature = "only-sig-bypass"), + feature = "regular" + ))] + sdk::configure_sdk(&mut interceptor); + #[cfg(all( + feature = "enable-sdk", + not(feature = "only-sig-bypass"), + feature = "regular" + ))] + curl_hook::configure_kr_curl( + &mut interceptor, + Some(CONFIG.kr_curl.curl_dll), + &CONFIG.kr_curl.curl_config, + &CONFIG.replacement_config, + ); println!("Successfully initialized!"); thread::sleep(Duration::from_secs(u64::MAX)); } +#[cfg(any(feature = "only-sig-bypass", feature = "regular"))] unsafe extern "win64" fn fpakfile_check_replacement( reg: *mut Registers, _: usize, _: usize, ) -> usize { - let wstr = *(((*reg).rcx + 8) as *const usize) as *const u16; - let pak_name = PCWSTR::from_raw(wstr).to_string().unwrap(); + let pak_name = unsafe { + PCWSTR::from_raw(*(((*reg).rcx + 8) as *const usize) as *const u16) + .to_string() + .unwrap() + }; println!("Trying to verify pak: {pak_name}, returning true"); 1 } unsafe extern "win64" fn add_pak_folders(reg: *mut Registers, _: usize) { - let local_ptr = ((*reg).rbp - 0x20) as usize; // Uninitialized local FString pointer + let local_ptr = unsafe { ((*reg).rbp - 0x20) as usize }; // Uninitialized local FString pointer let pak_folder = CUSTOM_PAK_FOLDER.get().unwrap(); - FString::printf(local_ptr, pak_folder); + let _ = FString::printf(local_ptr, pak_folder).unwrap(); let mut f_string = FString(TArray::read(local_ptr)); println!("Injecting custom pak folder: {}", f_string); - TArray::read((*reg).rdx as usize).add(&mut f_string.0); + unsafe { + TArray::read((*reg).rdx as usize).add(&mut f_string.0); + } } unsafe extern "win64" fn debug_get_pak_folders(reg: *mut Registers, _: usize) { - println!("Loading Paks from: {}", TArray::read((*reg).rbx as usize)); + println!("Loading Paks from: {}", unsafe { TArray::read((*reg).rbx as usize) }); } -#[no_mangle] +#[unsafe(no_mangle)] unsafe extern "system" fn DllMain(_: HINSTANCE, call_reason: u32, _: *mut ()) -> bool { if call_reason == DLL_PROCESS_ATTACH { thread::spawn(|| thread_func()); diff --git a/src/replacer.rs b/src/replacer.rs deleted file mode 100644 index 4ecc357..0000000 --- a/src/replacer.rs +++ /dev/null @@ -1,83 +0,0 @@ -#![cfg(all(not(feature = "only-sig-bypass"), feature = "regular"))] -pub(crate) trait Replacer { - fn replace(&mut self, original: &str) -> Result; -} - -#[derive(Debug)] -pub(crate) enum AbstractReplacer { - GenericReplacer(GenericReplacer), - GenericCdnReplacer(GenericCdnReplacer), -} - -#[derive(Debug)] -pub(crate) struct GenericReplacer { - pub(crate) regex: regex::Regex, - pub(crate) replacement: String, - pub(crate) force_http: bool, -} - -#[derive(Debug)] -pub(crate) struct GenericCdnReplacer { - pub(crate) regex: regex::Regex, - pub(crate) replacement: Vec, - pub(crate) force_http: bool, - pub(crate) url_index: u8, -} - -impl Replacer for AbstractReplacer { - fn replace(&mut self, original: &str) -> Result { - match self { - AbstractReplacer::GenericReplacer(replacer) => replacer.replace(original), - AbstractReplacer::GenericCdnReplacer(replacer) => replacer.replace(original) - } - } -} - -impl Replacer for GenericReplacer { - fn replace(&mut self, original: &str) -> Result { - // Prepare output array - let mut results: Vec = vec![]; - // Perform the capture over input - for (_, [scheme, path]) in self.regex.captures_iter(original).map(|c| c.extract()) { - results.push(format!( - "{}://{}/{}", - if self.force_http { "http" } else { scheme }, - self.replacement, - path - )); - } - // We are supposed to only parse one entry from text - if 1 == results.len() { - Ok(results.remove(0)) - } else if results.is_empty() { - Err("No valid url match found so returning original url".to_string()) - } else { - Err(format!("Invalid number of entries parsed, expected 1, obtained {:?}", results.len())) - } - } -} - -impl Replacer for GenericCdnReplacer { - fn replace(&mut self, original: &str) -> Result { - // Prepare output array - let mut results: Vec = vec![]; - // Perform the capture over input - for (_, [scheme, path]) in self.regex.captures_iter(original).map(|c| c.extract()) { - results.push(format!( - "{}://{}/{}", - if self.force_http { "http" } else { scheme }, - self.replacement[self.url_index as usize], - path - )); - } - // We are supposed to only parse one entry from text - if 1 == results.len() { - self.url_index = (self.url_index + 1) % self.replacement.len() as u8; - Ok(results.remove(0)) - } else if results.is_empty() { - Err("No valid url match found".to_string()) - } else { - Err(format!("Invalid number of entries parsed, expected 1, obtained {:?}", results.len())) - } - } -} \ No newline at end of file diff --git a/src/sdk.rs b/src/sdk.rs new file mode 100644 index 0000000..7d3dd24 --- /dev/null +++ b/src/sdk.rs @@ -0,0 +1,38 @@ +#![cfg(all(not(feature = "enable-sdk"), not(feature = "only-sig-bypass"), feature = "regular"))] + +use std::thread; +use std::time::Duration; + +use ilhook::x64::Registers; +use windows::Win32::System::LibraryLoader::GetModuleHandleA; + +use crate::config::CONFIG; + +pub(crate) fn configure_sdk(interceptor: &mut interceptor_rs::Interceptor) { + 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 +}