From e5af1753e7f6c6b4cdd2e26e9aa14f574fab8722 Mon Sep 17 00:00:00 2001 From: Jujstme Date: Tue, 30 Jan 2024 21:59:16 +0100 Subject: [PATCH 1/2] Added V1Cattrs offsets for mono --- src/game_engine/unity/mono.rs | 48 +++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index 3e63dc8..f99957c 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -476,7 +476,7 @@ impl Class { // Mono V1 behaves differently when it comes to recover the static table match module.version { - Version::V1 => Some(vtables + module.offsets.monoclass_vtable_size), + Version::V1 | Version::V1Cattrs => Some(vtables + module.offsets.monoclass_vtable_size), _ => { vtables = vtables + module.offsets.monovtable_vtable; @@ -800,7 +800,7 @@ struct Offsets { monoclass_name_space: u8, monoclass_fields: u8, monoclassdef_field_count: u16, - monoclass_runtime_info: u8, + monoclass_runtime_info: u16, monoclass_vtable_size: u8, monoclass_parent: u8, monoclassfield_name: u8, @@ -835,6 +835,27 @@ impl Offsets { monovtable_vtable: 0x48, monoclassfieldalignment: 0x20, }), + Version::V1Cattrs => Some(&Self { + monoassembly_aname: 0x10, + monoassembly_image: 0x58, + monoimage_class_cache: 0x3D0, + monointernalhashtable_table: 0x20, + monointernalhashtable_size: 0x18, + monoclassdef_next_class_cache: 0x108, + monoclassdef_klass: 0x0, + monoclass_name: 0x50, + monoclass_name_space: 0x58, + monoclass_fields: 0xB0, + monoclassdef_field_count: 0x9C, + monoclass_runtime_info: 0x100, + monoclass_vtable_size: 0x18, // MonoVtable.data + monoclass_parent: 0x30, + monoclassfield_name: 0x8, + monoclassfield_offset: 0x18, + monoclassruntimeinfo_domain_vtables: 0x8, + monovtable_vtable: 0x48, + monoclassfieldalignment: 0x20, + }), Version::V2 => Some(&Self { monoassembly_aname: 0x10, monoassembly_image: 0x60, @@ -900,6 +921,27 @@ impl Offsets { monovtable_vtable: 0x28, monoclassfieldalignment: 0x10, }), + Version::V1Cattrs => Some(&Self { + monoassembly_aname: 0x8, + monoassembly_image: 0x40, + monoimage_class_cache: 0x2A0, + monointernalhashtable_table: 0x14, + monointernalhashtable_size: 0xC, + monoclassdef_next_class_cache: 0xAC, + monoclassdef_klass: 0x0, + monoclass_name: 0x34, + monoclass_name_space: 0x38, + monoclass_fields: 0x78, + monoclassdef_field_count: 0x68, + monoclass_runtime_info: 0xA8, + monoclass_vtable_size: 0xC, // MonoVtable.data + monoclass_parent: 0x24, + monoclassfield_name: 0x4, + monoclassfield_offset: 0xC, + monoclassruntimeinfo_domain_vtables: 0x4, + monovtable_vtable: 0x28, + monoclassfieldalignment: 0x10, + }), Version::V2 => Some(&Self { monoassembly_aname: 0x8, monoassembly_image: 0x44, @@ -954,6 +996,8 @@ impl Offsets { pub enum Version { /// Version 1 V1, + /// Version 1 with cattrs + V1Cattrs, /// Version 2 V2, /// Version 3 From 62748097dc5da5a45e0a96944233e5f52c2f79e8 Mon Sep 17 00:00:00 2001 From: Jujstme Date: Tue, 30 Jan 2024 23:42:04 +0100 Subject: [PATCH 2/2] Added version autodetection --- src/game_engine/unity/mono.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index f99957c..112fb4d 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -1006,7 +1006,27 @@ pub enum Version { fn detect_version(process: &Process) -> Option { if process.get_module_address("mono.dll").is_ok() { - return Some(Version::V1); + // If the module mono.dll is present, then it's either V1 or V1Cattrs. + // In order to distinguish between them, we check the first class listed in the + // default Assembly-CSharp image and check for the pointer to its name, assuming it's using V1. + // If such pointer matches the address to the assembly image instead, then it's V1Cattrs. + // The idea is taken from https://github.com/Voxelse/Voxif/blob/main/Voxif.Helpers/Voxif.Helpers.UnityHelper/UnityHelper.cs#L343-L344 + let module = Module::attach(process, Version::V1)?; + let image = module.get_default_image(process)?; + let class = image.classes(process, &module).next()?; + + let pointer_to_image = process + .read_pointer( + class.class + module.offsets.monoclass_name, + module.pointer_size, + ) + .ok()?; + + return Some(if pointer_to_image.eq(&image.image) { + Version::V1Cattrs + } else { + Version::V1 + }); } let unity_module = {