Compare commits
No commits in common. "master" and "master" have entirely different histories.
15 changed files with 30 additions and 133 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -239,6 +239,16 @@ version = "1.0.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
|
||||
[[package]]
|
||||
name = "vivian"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"ilhook",
|
||||
"num_enum",
|
||||
"thiserror 2.0.11",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.59.0"
|
||||
|
@ -431,13 +441,3 @@ checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
|
|||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yixuan"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"ilhook",
|
||||
"num_enum",
|
||||
"thiserror 2.0.11",
|
||||
"windows",
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = ["launcher", "yixuan"]
|
||||
members = ["launcher", "vivian"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# yixuan-patch
|
||||
# vivian-patch
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use windows::Win32::System::Threading::{
|
|||
};
|
||||
|
||||
const GAME_EXECUTABLE: PCSTR = s!("ZenlessZoneZero.exe");
|
||||
const INJECT_DLL: &str = "yixuan.dll";
|
||||
const INJECT_DLL: &str = "vivian.dll";
|
||||
|
||||
fn inject_standard(h_target: HANDLE, dll_path: &str) -> bool {
|
||||
unsafe {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[package]
|
||||
name = "yixuan"
|
||||
name = "vivian"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "yixuan"
|
||||
name = "vivian"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
|
@ -2,7 +2,6 @@ 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,
|
||||
},
|
||||
|
@ -32,18 +31,12 @@ unsafe fn thread_fn() {
|
|||
thread::sleep(Duration::from_secs(5));
|
||||
util::disable_memory_protection();
|
||||
|
||||
println!("yixuan-patch (2.0.0 PROD) is initializing");
|
||||
|
||||
println!(
|
||||
"to work with yixuan-rs: https://git.xeondev.com/yixuan-rs/yixuan-rs"
|
||||
);
|
||||
|
||||
println!("\nJoin us on Discord at https://discord.gg/reversedrooms\n\n\n");
|
||||
println!("vivian-patch (1.7.0 PROD) is initializing");
|
||||
println!("to work with vivian-rs: https://git.xeondev.com/vivian-rs/vivian-rs");
|
||||
|
||||
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();
|
|
@ -7,14 +7,14 @@ use crate::{
|
|||
util::{import, GAME_ASSEMBLY_BASE},
|
||||
};
|
||||
|
||||
import!(rsa_create() -> usize = 0x1B56F0F0);
|
||||
import!(rsa_from_xml_string(instance: usize, xml_string: usize) -> usize = 0x1B56F330);
|
||||
import!(il2cpp_string_new(cstr: *const u8) -> usize = 0x115CCC0);
|
||||
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);
|
||||
|
||||
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(0x5550778) as *const usize)) + 252784) as *mut usize;
|
||||
((*(GAME_ASSEMBLY_BASE.wrapping_add(0x4E072F0) as *const usize)) + 235872) as *mut usize;
|
||||
|
||||
let rsa = rsa_create();
|
||||
rsa_from_xml_string(
|
||||
|
@ -33,38 +33,18 @@ 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(0x5952CA8) as *mut usize) = il2cpp_string_new(
|
||||
*(GAME_ASSEMBLY_BASE.wrapping_add(0x53D49C0) 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(0x59760D0) 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, 43266, 17556, 17415, 52254, 32830,
|
||||
]
|
||||
.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(0xDE28090),
|
||||
GAME_ASSEMBLY_BASE.wrapping_add(0xAE84F80),
|
||||
on_network_state_change,
|
||||
)
|
||||
.unwrap();
|
|
@ -4,10 +4,10 @@ use crate::util::GAME_ASSEMBLY_BASE;
|
|||
|
||||
use super::{ModuleInitError, NapModule, NapModuleContext};
|
||||
|
||||
const ON_COMBO_INIT_SUCCESS: usize = 0x1ACAB470;
|
||||
const STATICS: usize = 0x5550778;
|
||||
const STATIC_ID: usize = 34512;
|
||||
const FIELD_OFFSET: usize = 0x40;
|
||||
const ON_COMBO_INIT_SUCCESS: usize = 0x18AE4030;
|
||||
const STATICS: usize = 0x4E072F0;
|
||||
const STATIC_ID: usize = 34344;
|
||||
const FIELD_OFFSET: usize = 0x48;
|
||||
|
||||
pub struct HoyopassPatch;
|
||||
|
|
@ -2,7 +2,6 @@ use std::marker::PhantomData;
|
|||
|
||||
use crate::{interceptor::Interceptor, util};
|
||||
|
||||
pub mod censorship_patch;
|
||||
pub mod crypto;
|
||||
pub mod hoyopass_patch;
|
||||
pub mod network;
|
|
@ -2,12 +2,11 @@ use std::ffi::CString;
|
|||
|
||||
use ilhook::x64::Registers;
|
||||
|
||||
use crate::util::{self, import, read_csharp_string};
|
||||
use crate::util::{self, import};
|
||||
|
||||
use super::{ModuleInitError, NapModule, NapModuleContext};
|
||||
|
||||
const MAKE_INITIAL_URL: usize = 0x1D14BCE0;
|
||||
const WEB_REQUEST_CREATE: usize = 0x1CC33EF0;
|
||||
const MAKE_INITIAL_URL: usize = 0x1ACB6C70;
|
||||
|
||||
pub struct Network;
|
||||
|
||||
|
@ -18,26 +17,11 @@ 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(())
|
||||
}
|
||||
}
|
||||
|
||||
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 = 0x115CCC0);
|
||||
import!(il2cpp_string_new(cstr: *const u8) -> usize = 0x1242D60);
|
||||
|
||||
impl Network {
|
||||
const SDK_URL: &str = "http://127.0.0.1:20100";
|
|
@ -1,59 +0,0 @@
|
|||
use ilhook::x64::Registers;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use super::{ModuleInitError, NapModule, NapModuleContext};
|
||||
|
||||
const SET_DITHER_CONFIG: usize = 0x8CA93D0;
|
||||
const DITHER_CONFIG_AVATAR_USING_DITHER_ALPHA: usize = 0x49;
|
||||
|
||||
const ON_ENTER_SCENE_SC_NOTIFY: usize = 0x86E6F80;
|
||||
const ENTER_SCENE_SC_NOTIFY_SCENE_DATA: usize = 0x10;
|
||||
const SCENE_DATA_SCENE_TYPE: usize = 0x74;
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue