From a17517defcb4a2b06cd5b84bc74af557eb781151 Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Mon, 16 Oct 2023 17:34:05 -0400 Subject: [PATCH] Mac std attach Module --- src/game_engine/unity/mono.rs | 51 +++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index 46358c2..1f53b75 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -49,10 +49,19 @@ impl Module { /// correct for this function to work. If you don't know the version in /// advance, use [`attach_auto_detect`](Self::attach_auto_detect) instead. pub fn attach(process: &Process, version: Version) -> Option { - let module = ["mono.dll", "mono-2.0-bdwgc.dll"] + if let Some(module) = ["mono.dll", "mono-2.0-bdwgc.dll"] .iter() - .find_map(|&name| process.get_module_address(name).ok())?; + .find_map(|&name| process.get_module_address(name).ok()) { + return Self::attach_dll(process, version, module); + } + #[cfg(feature = "std")] + if let Ok(module_range) = process.get_module_range("libmonobdwgc-2.0.dylib") { + return Self::attach_dylib(process, version, module_range); + } + None + } + fn attach_dll(process: &Process, version: Version, module: Address) -> Option { let is_64_bit = pe::MachineType::read(process, module)? == pe::MachineType::X86_64; let offsets = Offsets::new(version, is_64_bit, BinaryFormat::PE); @@ -101,6 +110,44 @@ impl Module { } } + #[cfg(feature = "std")] + fn attach_dylib(process: &Process, version: Version, module_range: (Address, u64)) -> Option { + let is_64_bit = macho::is_64_bit(process, macho::scan_macho_page(process, module_range)?)?; + let offsets = Offsets::new(version, is_64_bit, BinaryFormat::MachO); + + let process_path = process.get_path().ok()?; + let contents_path = Path::new(&process_path).parent()?.parent()?; + let mono_module_path = contents_path.join("Frameworks").join("libmonobdwgc-2.0.dylib"); + let mono_module_bytes = file_read_all_bytes(mono_module_path).ok()?; + + let mono_assembly_foreach_offset: u32 = macho::get_function_offset(&mono_module_bytes, b"_mono_assembly_foreach")?; + + let function_array: [u8; 0x100] = macho::slice_read(&mono_module_bytes, mono_assembly_foreach_offset as usize).ok()?; + let sig_function_array: Signature<0x100> = Signature::Simple(function_array); + let mono_assembly_foreach_address = sig_function_array.scan_process_range(process, module_range)?; + + let assemblies: Address = match is_64_bit { + true => { + const SIG_MONO_64_DYLIB: Signature<3> = Signature::new("48 8B 3D"); + // RIP-relative addressing + // 3 is the offset to the next thing after the signature + let scan_address = SIG_MONO_64_DYLIB.scan_process_range(process, (mono_assembly_foreach_address, 0x100))? + 3; + // 4 is the offset to the next instruction after relative + scan_address + 0x4 + process.read::(scan_address).ok()? + } + false => { + return None; + } + }; + + Some(Self { + is_64_bit, + version, + offsets, + assemblies, + }) + } + fn assemblies<'a>(&'a self, process: &'a Process) -> impl Iterator + 'a { let mut assembly = self.assemblies; let mut iter_break = assembly.is_null();