Compare commits

...

6 commits

7 changed files with 117 additions and 16 deletions

View file

@ -12,7 +12,7 @@ use windows::Win32::System::Threading::{
PROCESS_INFORMATION, STARTUPINFOA,
};
const GAME_EXECUTABLE: PCSTR = s!("ZenlessZoneZero.exe");
const GAME_EXECUTABLE: PCSTR = s!("ZenlessZoneZeroBeta.exe");
const INJECT_DLL: &str = "vivian.dll";
fn inject_standard(h_target: HANDLE, dll_path: &str) -> bool {

View file

@ -2,6 +2,7 @@ use std::{thread, time::Duration};
use interceptor::Interceptor;
use modules::{
censorship_patch::CensorshipPatch,
crypto::{
initialize_rsa_public_key, monitor_network_state, replace_sdk_public_key_string_literal,
},
@ -31,12 +32,18 @@ unsafe fn thread_fn() {
thread::sleep(Duration::from_secs(5));
util::disable_memory_protection();
println!("vivian-patch (1.7.0 PROD) is initializing");
println!("to work with vivian-rs: https://git.xeondev.com/vivian-rs/vivian-rs");
println!("vivian-patch (2.0.12 KOL) is initializing");
println!(
"to work with vivian-rs: https://git.xeondev.com/vivian-rs/vivian-rs/src/branch/2.0_beta"
);
println!("\nJoin us on Discord at https://discord.gg/reversedrooms\n\n\n");
let mut module_manager = NapModuleManager::default();
module_manager.add::<Network>();
module_manager.add::<HoyopassPatch>();
module_manager.add::<CensorshipPatch>();
module_manager.init().expect("failed to initialize modules");
initialize_rsa_public_key();

View file

@ -0,0 +1,59 @@
use ilhook::x64::Registers;
use std::sync::atomic::{AtomicU32, Ordering};
use super::{ModuleInitError, NapModule, NapModuleContext};
const SET_DITHER_CONFIG: usize = 0xAC49A20;
const DITHER_CONFIG_AVATAR_USING_DITHER_ALPHA: usize = 0x41;
const ON_ENTER_SCENE_SC_NOTIFY: usize = 0xCC97000;
const ENTER_SCENE_SC_NOTIFY_SCENE_DATA: usize = 0x20;
const SCENE_DATA_SCENE_TYPE: usize = 0x6C;
const SCENE_TYPE_HALL: u32 = 1;
static LAST_ENTER_SCENE_TYPE: AtomicU32 = AtomicU32::new(0);
pub struct CensorshipPatch;
impl NapModule for NapModuleContext<CensorshipPatch> {
unsafe fn init(&mut self) -> Result<(), ModuleInitError> {
self.interceptor.attach(
self.base.wrapping_add(SET_DITHER_CONFIG),
CensorshipPatch::on_set_dither_config,
)?;
self.interceptor.attach(
self.base.wrapping_add(ON_ENTER_SCENE_SC_NOTIFY),
CensorshipPatch::on_enter_scene_sc_notify,
)?;
Ok(())
}
}
impl CensorshipPatch {
pub unsafe extern "win64" fn on_set_dither_config(reg: *mut Registers, _: usize) {
if LAST_ENTER_SCENE_TYPE.load(Ordering::SeqCst) == SCENE_TYPE_HALL {
if (*reg).rdx != 0 {
println!("SetDitherConfig: disabling dither alpha");
*(((*reg).rdx as *mut u8).wrapping_add(DITHER_CONFIG_AVATAR_USING_DITHER_ALPHA)) = 0;
}
} else {
println!("SetDitherConfig: not in hall, ignoring");
}
}
pub unsafe extern "win64" fn on_enter_scene_sc_notify(reg: *mut Registers, _: usize) {
let scene_data = *((*reg).rdx as *const u8)
.wrapping_add(ENTER_SCENE_SC_NOTIFY_SCENE_DATA)
.cast::<usize>();
let scene_type = *(scene_data as *const u8)
.wrapping_add(SCENE_DATA_SCENE_TYPE)
.cast::<u32>();
println!("EnterSceneScNotify scene_type: {scene_type}");
LAST_ENTER_SCENE_TYPE.store(scene_type, Ordering::SeqCst);
}
}

View file

@ -7,14 +7,14 @@ use crate::{
util::{import, GAME_ASSEMBLY_BASE},
};
import!(rsa_create() -> usize = 0x19034F20);
import!(rsa_from_xml_string(instance: usize, xml_string: usize) -> usize = 0x19035160);
import!(il2cpp_string_new(cstr: *const u8) -> usize = 0x1242D60);
import!(rsa_create() -> usize = 0x1B583DD0);
import!(rsa_from_xml_string(instance: usize, xml_string: usize) -> usize = 0x1B584010);
import!(il2cpp_string_new(cstr: *const u8) -> usize = 0x1162FC0);
pub unsafe fn initialize_rsa_public_key() {
const SERVER_PUBLIC_KEY: &str = include_str!("../../server_public_key.xml");
let rsa_public_key_backdoor_field =
((*(GAME_ASSEMBLY_BASE.wrapping_add(0x4E072F0) as *const usize)) + 235872) as *mut usize;
((*(GAME_ASSEMBLY_BASE.wrapping_add(0x55594B8) as *const usize)) + 252856) as *mut usize;
let rsa = rsa_create();
rsa_from_xml_string(
@ -33,18 +33,36 @@ pub unsafe fn initialize_rsa_public_key() {
pub unsafe fn replace_sdk_public_key_string_literal() {
const SDK_PUBLIC_KEY: &str = include_str!("../../sdk_public_key.xml");
*(GAME_ASSEMBLY_BASE.wrapping_add(0x53D49C0) as *mut usize) = il2cpp_string_new(
*(GAME_ASSEMBLY_BASE.wrapping_add(0x595BC00) as *mut usize) = il2cpp_string_new(
CString::new(SDK_PUBLIC_KEY)
.unwrap()
.to_bytes_with_nul()
.as_ptr(),
) as usize;
*(GAME_ASSEMBLY_BASE.wrapping_add(0x597F010) as *mut usize) = il2cpp_string_new(
[27818, 40348, 47410, 27936, 51394, 33172, 51987, 8709, 44748,
23705, 45753, 21092, 57054, 52661, 369, 62630, 11725, 7496, 36921, 28271,
34880, 52645, 31515, 18214, 3108, 2077, 13490, 25459, 58590, 47504, 15163,
8951, 44748, 23705, 45753, 29284, 57054, 52661]
.into_iter()
.enumerate()
.flat_map(|(i, v)| {
let b = (((i + ((i >> 31) >> 29)) & 0xF8).wrapping_sub(i)) as i16;
(((v << ((b + 11) & 0xF)) | (v >> ((-11 - b) & 0xF))) & 0xFFFF_u16)
.to_be_bytes()
.into_iter()
})
.chain([0])
.collect::<Vec<_>>()
.as_ptr(),
) as usize;
}
pub unsafe fn monitor_network_state(interceptor: &mut Interceptor) {
interceptor
.attach(
GAME_ASSEMBLY_BASE.wrapping_add(0xAE84F80),
GAME_ASSEMBLY_BASE.wrapping_add(0xD952A20),
on_network_state_change,
)
.unwrap();

View file

@ -4,10 +4,10 @@ use crate::util::GAME_ASSEMBLY_BASE;
use super::{ModuleInitError, NapModule, NapModuleContext};
const ON_COMBO_INIT_SUCCESS: usize = 0x18AE4030;
const STATICS: usize = 0x4E072F0;
const STATIC_ID: usize = 34344;
const FIELD_OFFSET: usize = 0x48;
const ON_COMBO_INIT_SUCCESS: usize = 0x1ACEFC40;
const STATICS: usize = 0x55594B8;
const STATIC_ID: usize = 34496;
const FIELD_OFFSET: usize = 0x44;
pub struct HoyopassPatch;

View file

@ -2,6 +2,7 @@ use std::marker::PhantomData;
use crate::{interceptor::Interceptor, util};
pub mod censorship_patch;
pub mod crypto;
pub mod hoyopass_patch;
pub mod network;

View file

@ -2,11 +2,12 @@ use std::ffi::CString;
use ilhook::x64::Registers;
use crate::util::{self, import};
use crate::util::{self, import, read_csharp_string};
use super::{ModuleInitError, NapModule, NapModuleContext};
const MAKE_INITIAL_URL: usize = 0x1ACB6C70;
const MAKE_INITIAL_URL: usize = 0x1D17D450;
const WEB_REQUEST_CREATE: usize = 0x1CC6BD90;
pub struct Network;
@ -17,11 +18,26 @@ impl NapModule for NapModuleContext<Network> {
Network::on_make_initial_url,
)?;
self.interceptor.attach(
self.base.wrapping_add(WEB_REQUEST_CREATE),
on_web_request_create,
)?;
Ok(())
}
}
import!(il2cpp_string_new(cstr: *const u8) -> usize = 0x1242D60);
unsafe extern "win64" fn on_web_request_create(reg: *mut Registers, _: usize) {
let s = read_csharp_string((*reg).rcx as usize);
if s.contains("StandaloneWindows64/cn/") {
let s = s.replace("StandaloneWindows64/cn/", "StandaloneWindows64/oversea/");
println!("replaced: {s}");
(*reg).rcx =
il2cpp_string_new(CString::new(s).unwrap().to_bytes_with_nul().as_ptr()) as u64;
}
}
import!(il2cpp_string_new(cstr: *const u8) -> usize = 0x1162FC0);
impl Network {
const SDK_URL: &str = "http://127.0.0.1:20100";