From 675f952192aef8ab88924234bc5883a55d4a4aeb Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Sun, 28 Jan 2024 15:40:33 -0500 Subject: [PATCH 1/7] Separate MonoAssemblyOffsets, MonoClassOffsets --- src/game_engine/unity/mono.rs | 200 ++++++++++++++++++++-------------- 1 file changed, 118 insertions(+), 82 deletions(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index 3e63dc8..f2a8e00 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -17,7 +17,7 @@ const CSTR: usize = 128; pub struct Module { pointer_size: PointerSize, version: Version, - offsets: &'static Offsets, + offsets: &'static MonoAssemblyOffsets, assemblies: Address, } @@ -45,7 +45,7 @@ impl Module { _ => PointerSize::Bit32, }; - let offsets = Offsets::new(version, pointer_size)?; + let offsets = MonoAssemblyOffsets::new(version, pointer_size)?; let root_domain_function_address = pe::symbols(process, module) .find(|symbol| { @@ -220,14 +220,17 @@ impl Assembly { } fn get_image(&self, process: &Process, module: &Module) -> Option { + let image = process + .read_pointer( + self.assembly + module.offsets.monoassembly_image, + module.pointer_size, + ) + .ok() + .filter(|val| !val.is_null())?; + let offsets = MonoClassOffsets::new(module.version, module.pointer_size)?; Some(Image { - image: process - .read_pointer( - self.assembly + module.offsets.monoassembly_image, - module.pointer_size, - ) - .ok() - .filter(|val| !val.is_null())?, + image, + offsets, }) } } @@ -237,6 +240,7 @@ impl Assembly { #[derive(Copy, Clone)] pub struct Image { image: Address, + offsets: &'static MonoClassOffsets, } impl Image { @@ -265,6 +269,8 @@ impl Image { _ => Err(Error {}), }; + let offsets: &'static MonoClassOffsets = self.offsets; + (0..class_cache_size.unwrap_or_default()).flat_map(move |i| { let mut table = match table_addr { Ok(table_addr) => process @@ -281,13 +287,13 @@ impl Image { table = process .read_pointer( - table? + module.offsets.monoclassdef_next_class_cache, + table? + offsets.monoclassdef_next_class_cache, module.pointer_size, ) .ok() .filter(|val| !val.is_null()); - Some(Class { class }) + Some(Class { class, offsets }) }) }) } @@ -318,6 +324,7 @@ impl Image { #[derive(Copy, Clone)] pub struct Class { class: Address, + offsets: &'static MonoClassOffsets, } impl Class { @@ -330,7 +337,7 @@ impl Class { self.class, module.pointer_size, &[ - module.offsets.monoclassdef_klass as u64 + module.offsets.monoclass_name as u64, + self.offsets.monoclassdef_klass as u64 + self.offsets.monoclass_name as u64, 0x0, ], ) @@ -345,8 +352,8 @@ impl Class { self.class, module.pointer_size, &[ - module.offsets.monoclassdef_klass as u64 - + module.offsets.monoclass_name_space as u64, + self.offsets.monoclassdef_klass as u64 + + self.offsets.monoclass_name_space as u64, 0x0, ], ) @@ -357,7 +364,7 @@ impl Class { process: &'a Process, module: &'a Module, ) -> impl Iterator + 'a { - let mut this_class = Class { class: self.class }; + let mut this_class = Class { class: self.class, offsets: self.offsets }; let mut iter_break = this_class.class.is_null(); iter::from_fn(move || { @@ -372,7 +379,7 @@ impl Class { .is_ok_and(|name| !name.matches("UnityEngine")) { let field_count = process - .read::(this_class.class + module.offsets.monoclassdef_field_count) + .read::(this_class.class + self.offsets.monoclassdef_field_count) .ok() .filter(|&val| val != 0); @@ -380,8 +387,8 @@ impl Class { Some(_) => process .read_pointer( this_class.class - + module.offsets.monoclassdef_klass - + module.offsets.monoclass_fields, + + self.offsets.monoclassdef_klass + + self.offsets.monoclass_fields, module.pointer_size, ) .ok(), @@ -461,8 +468,8 @@ impl Class { let runtime_info = process .read_pointer( self.class - + module.offsets.monoclassdef_klass - + module.offsets.monoclass_runtime_info, + + self.offsets.monoclassdef_klass + + self.offsets.monoclass_runtime_info, module.pointer_size, ) .ok()?; @@ -476,15 +483,15 @@ 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 => Some(vtables + self.offsets.monoclass_vtable_size), _ => { vtables = vtables + module.offsets.monovtable_vtable; let vtable_size = process .read::( self.class - + module.offsets.monoclassdef_klass - + module.offsets.monoclass_vtable_size, + + self.offsets.monoclassdef_klass + + self.offsets.monoclass_vtable_size, ) .ok()?; @@ -509,7 +516,7 @@ impl Class { pub fn get_parent(&self, process: &Process, module: &Module) -> Option { let parent_addr = process .read_pointer( - self.class + module.offsets.monoclassdef_klass + module.offsets.monoclass_parent, + self.class + self.offsets.monoclassdef_klass + self.offsets.monoclass_parent, module.pointer_size, ) .ok() @@ -520,6 +527,7 @@ impl Class { .read_pointer(parent_addr, module.pointer_size) .ok() .filter(|val| !val.is_null())?, + offsets: self.offsets, }) } @@ -706,7 +714,7 @@ impl UnityPointer { .filter(|val| !val.is_null()) .ok_or(Error {})?; - Class { class } + Class { class, offsets: image.offsets } } }; @@ -788,12 +796,20 @@ impl UnityPointer { } } -struct Offsets { +struct MonoAssemblyOffsets { monoassembly_aname: u8, monoassembly_image: u8, monoimage_class_cache: u16, monointernalhashtable_table: u8, monointernalhashtable_size: u8, + monoclassfield_name: u8, + monoclassfield_offset: u8, + monoclassruntimeinfo_domain_vtables: u8, + monovtable_vtable: u8, + monoclassfieldalignment: u8, +} + +struct MonoClassOffsets { monoclassdef_next_class_cache: u16, monoclassdef_klass: u8, monoclass_name: u8, @@ -803,14 +819,9 @@ struct Offsets { monoclass_runtime_info: u8, monoclass_vtable_size: u8, monoclass_parent: u8, - monoclassfield_name: u8, - monoclassfield_offset: u8, - monoclassruntimeinfo_domain_vtables: u8, - monovtable_vtable: u8, - monoclassfieldalignment: u8, } -impl Offsets { +impl MonoAssemblyOffsets { const fn new(version: Version, pointer_size: PointerSize) -> Option<&'static Self> { match pointer_size { PointerSize::Bit64 => match version { @@ -820,15 +831,6 @@ impl Offsets { monoimage_class_cache: 0x3D0, monointernalhashtable_table: 0x20, monointernalhashtable_size: 0x18, - monoclassdef_next_class_cache: 0x100, - monoclassdef_klass: 0x0, - monoclass_name: 0x48, - monoclass_name_space: 0x50, - monoclass_fields: 0xA8, - monoclassdef_field_count: 0x94, - monoclass_runtime_info: 0xF8, - monoclass_vtable_size: 0x18, // MonoVtable.data - monoclass_parent: 0x30, monoclassfield_name: 0x8, monoclassfield_offset: 0x18, monoclassruntimeinfo_domain_vtables: 0x8, @@ -841,15 +843,6 @@ impl Offsets { monoimage_class_cache: 0x4C0, monointernalhashtable_table: 0x20, monointernalhashtable_size: 0x18, - monoclassdef_next_class_cache: 0x108, - monoclassdef_klass: 0x0, - monoclass_name: 0x48, - monoclass_name_space: 0x50, - monoclass_fields: 0x98, - monoclassdef_field_count: 0x100, - monoclass_runtime_info: 0xD0, - monoclass_vtable_size: 0x5C, - monoclass_parent: 0x30, monoclassfield_name: 0x8, monoclassfield_offset: 0x18, monoclassruntimeinfo_domain_vtables: 0x8, @@ -862,15 +855,6 @@ impl Offsets { monoimage_class_cache: 0x4D0, monointernalhashtable_table: 0x20, monointernalhashtable_size: 0x18, - monoclassdef_next_class_cache: 0x108, - monoclassdef_klass: 0x0, - monoclass_name: 0x48, - monoclass_name_space: 0x50, - monoclass_fields: 0x98, - monoclassdef_field_count: 0x100, - monoclass_runtime_info: 0xD0, - monoclass_vtable_size: 0x5C, - monoclass_parent: 0x30, monoclassfield_name: 0x8, monoclassfield_offset: 0x18, monoclassruntimeinfo_domain_vtables: 0x8, @@ -885,15 +869,6 @@ impl Offsets { monoimage_class_cache: 0x2A0, monointernalhashtable_table: 0x14, monointernalhashtable_size: 0xC, - monoclassdef_next_class_cache: 0xA8, - monoclassdef_klass: 0x0, - monoclass_name: 0x30, - monoclass_name_space: 0x34, - monoclass_fields: 0x74, - monoclassdef_field_count: 0x64, - monoclass_runtime_info: 0xA4, - monoclass_vtable_size: 0xC, // MonoVtable.data - monoclass_parent: 0x24, monoclassfield_name: 0x4, monoclassfield_offset: 0xC, monoclassruntimeinfo_domain_vtables: 0x4, @@ -906,15 +881,6 @@ impl Offsets { monoimage_class_cache: 0x354, monointernalhashtable_table: 0x14, monointernalhashtable_size: 0xC, - monoclassdef_next_class_cache: 0xA8, - monoclassdef_klass: 0x0, - monoclass_name: 0x2C, - monoclass_name_space: 0x30, - monoclass_fields: 0x60, - monoclassdef_field_count: 0xA4, - monoclass_runtime_info: 0x84, - monoclass_vtable_size: 0x38, - monoclass_parent: 0x20, monoclassfield_name: 0x4, monoclassfield_offset: 0xC, monoclassruntimeinfo_domain_vtables: 0x4, @@ -927,6 +893,81 @@ impl Offsets { monoimage_class_cache: 0x35C, monointernalhashtable_table: 0x14, monointernalhashtable_size: 0xC, + monoclassfield_name: 0x4, + monoclassfield_offset: 0xC, + monoclassruntimeinfo_domain_vtables: 0x4, + monovtable_vtable: 0x2C, + monoclassfieldalignment: 0x10, + }), + }, + _ => None, + } + } +} + + +impl MonoClassOffsets { + const fn new(version: Version, pointer_size: PointerSize) -> Option<&'static Self> { + match pointer_size { + PointerSize::Bit64 => match version { + Version::V1 => Some(&Self { + monoclassdef_next_class_cache: 0x100, + monoclassdef_klass: 0x0, + monoclass_name: 0x48, + monoclass_name_space: 0x50, + monoclass_fields: 0xA8, + monoclassdef_field_count: 0x94, + monoclass_runtime_info: 0xF8, + monoclass_vtable_size: 0x18, // MonoVtable.data + monoclass_parent: 0x30, + }), + Version::V2 => Some(&Self { + monoclassdef_next_class_cache: 0x108, + monoclassdef_klass: 0x0, + monoclass_name: 0x48, + monoclass_name_space: 0x50, + monoclass_fields: 0x98, + monoclassdef_field_count: 0x100, + monoclass_runtime_info: 0xD0, + monoclass_vtable_size: 0x5C, + monoclass_parent: 0x30, + }), + Version::V3 => Some(&Self { + monoclassdef_next_class_cache: 0x108, + monoclassdef_klass: 0x0, + monoclass_name: 0x48, + monoclass_name_space: 0x50, + monoclass_fields: 0x98, + monoclassdef_field_count: 0x100, + monoclass_runtime_info: 0xD0, + monoclass_vtable_size: 0x5C, + monoclass_parent: 0x30, + }), + }, + PointerSize::Bit32 => match version { + Version::V1 => Some(&Self { + monoclassdef_next_class_cache: 0xA8, + monoclassdef_klass: 0x0, + monoclass_name: 0x30, + monoclass_name_space: 0x34, + monoclass_fields: 0x74, + monoclassdef_field_count: 0x64, + monoclass_runtime_info: 0xA4, + monoclass_vtable_size: 0xC, // MonoVtable.data + monoclass_parent: 0x24, + }), + Version::V2 => Some(&Self { + monoclassdef_next_class_cache: 0xA8, + monoclassdef_klass: 0x0, + monoclass_name: 0x2C, + monoclass_name_space: 0x30, + monoclass_fields: 0x60, + monoclassdef_field_count: 0xA4, + monoclass_runtime_info: 0x84, + monoclass_vtable_size: 0x38, + monoclass_parent: 0x20, + }), + Version::V3 => Some(&Self { monoclassdef_next_class_cache: 0xA0, monoclassdef_klass: 0x0, monoclass_name: 0x2C, @@ -936,11 +977,6 @@ impl Offsets { monoclass_runtime_info: 0x7C, monoclass_vtable_size: 0x38, monoclass_parent: 0x20, - monoclassfield_name: 0x4, - monoclassfield_offset: 0xC, - monoclassruntimeinfo_domain_vtables: 0x4, - monovtable_vtable: 0x2C, - monoclassfieldalignment: 0x10, }), }, _ => None, From 8c4205783a39be9b6678feb6756628f3b6f08616 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Sun, 28 Jan 2024 16:39:43 -0500 Subject: [PATCH 2/7] Add monoclass_image --- src/game_engine/unity/mono.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index f2a8e00..629c6e2 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -812,6 +812,7 @@ struct MonoAssemblyOffsets { struct MonoClassOffsets { monoclassdef_next_class_cache: u16, monoclassdef_klass: u8, + monoclass_image: u8, monoclass_name: u8, monoclass_name_space: u8, monoclass_fields: u8, @@ -913,6 +914,7 @@ impl MonoClassOffsets { Version::V1 => Some(&Self { monoclassdef_next_class_cache: 0x100, monoclassdef_klass: 0x0, + monoclass_image: 0x40, monoclass_name: 0x48, monoclass_name_space: 0x50, monoclass_fields: 0xA8, @@ -924,6 +926,7 @@ impl MonoClassOffsets { Version::V2 => Some(&Self { monoclassdef_next_class_cache: 0x108, monoclassdef_klass: 0x0, + monoclass_image: 0x40, monoclass_name: 0x48, monoclass_name_space: 0x50, monoclass_fields: 0x98, @@ -935,6 +938,7 @@ impl MonoClassOffsets { Version::V3 => Some(&Self { monoclassdef_next_class_cache: 0x108, monoclassdef_klass: 0x0, + monoclass_image: 0x40, monoclass_name: 0x48, monoclass_name_space: 0x50, monoclass_fields: 0x98, @@ -948,6 +952,7 @@ impl MonoClassOffsets { Version::V1 => Some(&Self { monoclassdef_next_class_cache: 0xA8, monoclassdef_klass: 0x0, + monoclass_image: 0x2C, monoclass_name: 0x30, monoclass_name_space: 0x34, monoclass_fields: 0x74, @@ -959,6 +964,7 @@ impl MonoClassOffsets { Version::V2 => Some(&Self { monoclassdef_next_class_cache: 0xA8, monoclassdef_klass: 0x0, + monoclass_image: 0x28, monoclass_name: 0x2C, monoclass_name_space: 0x30, monoclass_fields: 0x60, @@ -970,6 +976,7 @@ impl MonoClassOffsets { Version::V3 => Some(&Self { monoclassdef_next_class_cache: 0xA0, monoclassdef_klass: 0x0, + monoclass_image: 0x28, monoclass_name: 0x2C, monoclass_name_space: 0x30, monoclass_fields: 0x60, From 318b703fb8f99576851b326021ebf7c9871e4d1f Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Sun, 28 Jan 2024 16:44:38 -0500 Subject: [PATCH 3/7] check monoclass_image --- src/game_engine/unity/mono.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index 629c6e2..aabfa8f 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -228,6 +228,12 @@ impl Assembly { .ok() .filter(|val| !val.is_null())?; let offsets = MonoClassOffsets::new(module.version, module.pointer_size)?; + let table_addr = process.read_pointer(image + module.offsets.monoimage_class_cache + module.offsets.monointernalhashtable_table, module.pointer_size).ok()?; + let table = process.read_pointer(table_addr, module.pointer_size).ok()?; + let class = process.read_pointer(table, module.pointer_size).ok()?; + if process.read_pointer(class + offsets.monoclassdef_klass + offsets.monoclass_image, module.pointer_size).is_ok_and(|a| a == image) { + return Some(Image { image, offsets }); + } Some(Image { image, offsets, From 6c8f215ad2a83fc116cb6aece427e0d187f43175 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Sun, 28 Jan 2024 16:48:43 -0500 Subject: [PATCH 4/7] Add offsets for Bit32 V1 cattrs --- src/game_engine/unity/mono.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index aabfa8f..4fafa63 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -227,13 +227,19 @@ impl Assembly { ) .ok() .filter(|val| !val.is_null())?; - let offsets = MonoClassOffsets::new(module.version, module.pointer_size)?; + // try no cattrs first + let offsets = MonoClassOffsets::new(module.version, module.pointer_size, false)?; let table_addr = process.read_pointer(image + module.offsets.monoimage_class_cache + module.offsets.monointernalhashtable_table, module.pointer_size).ok()?; let table = process.read_pointer(table_addr, module.pointer_size).ok()?; let class = process.read_pointer(table, module.pointer_size).ok()?; if process.read_pointer(class + offsets.monoclassdef_klass + offsets.monoclass_image, module.pointer_size).is_ok_and(|a| a == image) { return Some(Image { image, offsets }); } + // then try cattrs + let offsets_cattrs = MonoClassOffsets::new(module.version, module.pointer_size, true)?; + if process.read_pointer(class + offsets_cattrs.monoclassdef_klass + offsets_cattrs.monoclass_image, module.pointer_size).is_ok_and(|a| a == image) { + return Some(Image { image, offsets: offsets_cattrs }); + } Some(Image { image, offsets, @@ -914,7 +920,7 @@ impl MonoAssemblyOffsets { impl MonoClassOffsets { - const fn new(version: Version, pointer_size: PointerSize) -> Option<&'static Self> { + const fn new(version: Version, pointer_size: PointerSize, cattrs: bool) -> Option<&'static Self> { match pointer_size { PointerSize::Bit64 => match version { Version::V1 => Some(&Self { @@ -955,6 +961,18 @@ impl MonoClassOffsets { }), }, PointerSize::Bit32 => match version { + Version::V1 if cattrs => Some(&Self { + monoclassdef_next_class_cache: 0xAC, + monoclassdef_klass: 0x0, + monoclass_image: 0x30, + 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, + }), Version::V1 => Some(&Self { monoclassdef_next_class_cache: 0xA8, monoclassdef_klass: 0x0, From 8cecccd42ef6e248f56742099053b23eb00218c8 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Sun, 28 Jan 2024 16:53:01 -0500 Subject: [PATCH 5/7] Add offsets for Bit64 V1 cattrs --- src/game_engine/unity/mono.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index 4fafa63..b4c8100 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -829,7 +829,7 @@ struct MonoClassOffsets { 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, } @@ -923,6 +923,18 @@ impl MonoClassOffsets { const fn new(version: Version, pointer_size: PointerSize, cattrs: bool) -> Option<&'static Self> { match pointer_size { PointerSize::Bit64 => match version { + Version::V1 if cattrs => Some(&Self { + monoclassdef_next_class_cache: 0x108, + monoclassdef_klass: 0x0, + monoclass_image: 0x48, + 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, + }), Version::V1 => Some(&Self { monoclassdef_next_class_cache: 0x100, monoclassdef_klass: 0x0, From 8aab8fb34fdb2330c111dfd755e060800065e7f5 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Sun, 28 Jan 2024 17:34:28 -0500 Subject: [PATCH 6/7] cargo fmt --- src/game_engine/unity/mono.rs | 59 +++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index b4c8100..2dda427 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -229,21 +229,40 @@ impl Assembly { .filter(|val| !val.is_null())?; // try no cattrs first let offsets = MonoClassOffsets::new(module.version, module.pointer_size, false)?; - let table_addr = process.read_pointer(image + module.offsets.monoimage_class_cache + module.offsets.monointernalhashtable_table, module.pointer_size).ok()?; + let table_addr = process + .read_pointer( + image + + module.offsets.monoimage_class_cache + + module.offsets.monointernalhashtable_table, + module.pointer_size, + ) + .ok()?; let table = process.read_pointer(table_addr, module.pointer_size).ok()?; let class = process.read_pointer(table, module.pointer_size).ok()?; - if process.read_pointer(class + offsets.monoclassdef_klass + offsets.monoclass_image, module.pointer_size).is_ok_and(|a| a == image) { + if process + .read_pointer( + class + offsets.monoclassdef_klass + offsets.monoclass_image, + module.pointer_size, + ) + .is_ok_and(|a| a == image) + { return Some(Image { image, offsets }); } // then try cattrs let offsets_cattrs = MonoClassOffsets::new(module.version, module.pointer_size, true)?; - if process.read_pointer(class + offsets_cattrs.monoclassdef_klass + offsets_cattrs.monoclass_image, module.pointer_size).is_ok_and(|a| a == image) { - return Some(Image { image, offsets: offsets_cattrs }); + if process + .read_pointer( + class + offsets_cattrs.monoclassdef_klass + offsets_cattrs.monoclass_image, + module.pointer_size, + ) + .is_ok_and(|a| a == image) + { + return Some(Image { + image, + offsets: offsets_cattrs, + }); } - Some(Image { - image, - offsets, - }) + Some(Image { image, offsets }) } } @@ -364,8 +383,7 @@ impl Class { self.class, module.pointer_size, &[ - self.offsets.monoclassdef_klass as u64 - + self.offsets.monoclass_name_space as u64, + self.offsets.monoclassdef_klass as u64 + self.offsets.monoclass_name_space as u64, 0x0, ], ) @@ -376,7 +394,10 @@ impl Class { process: &'a Process, module: &'a Module, ) -> impl Iterator + 'a { - let mut this_class = Class { class: self.class, offsets: self.offsets }; + let mut this_class = Class { + class: self.class, + offsets: self.offsets, + }; let mut iter_break = this_class.class.is_null(); iter::from_fn(move || { @@ -479,9 +500,7 @@ impl Class { fn get_static_table_pointer(&self, process: &Process, module: &Module) -> Option
{ let runtime_info = process .read_pointer( - self.class - + self.offsets.monoclassdef_klass - + self.offsets.monoclass_runtime_info, + self.class + self.offsets.monoclassdef_klass + self.offsets.monoclass_runtime_info, module.pointer_size, ) .ok()?; @@ -726,7 +745,10 @@ impl UnityPointer { .filter(|val| !val.is_null()) .ok_or(Error {})?; - Class { class, offsets: image.offsets } + Class { + class, + offsets: image.offsets, + } } }; @@ -918,9 +940,12 @@ impl MonoAssemblyOffsets { } } - impl MonoClassOffsets { - const fn new(version: Version, pointer_size: PointerSize, cattrs: bool) -> Option<&'static Self> { + const fn new( + version: Version, + pointer_size: PointerSize, + cattrs: bool, + ) -> Option<&'static Self> { match pointer_size { PointerSize::Bit64 => match version { Version::V1 if cattrs => Some(&Self { From 3f3e3ab43206c79bdfb7c8d5babfba53d0596e01 Mon Sep 17 00:00:00 2001 From: AlexKnauth Date: Tue, 30 Jan 2024 15:55:46 -0500 Subject: [PATCH 7/7] V1Cattrs TODO: update detect_version to distinguish between V1 and V1Cattrs before attach --- src/game_engine/unity/mono.rs | 41 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/game_engine/unity/mono.rs b/src/game_engine/unity/mono.rs index 2dda427..efb3126 100644 --- a/src/game_engine/unity/mono.rs +++ b/src/game_engine/unity/mono.rs @@ -228,7 +228,7 @@ impl Assembly { .ok() .filter(|val| !val.is_null())?; // try no cattrs first - let offsets = MonoClassOffsets::new(module.version, module.pointer_size, false)?; + let offsets = MonoClassOffsets::new(module.version, module.pointer_size)?; let table_addr = process .read_pointer( image @@ -249,18 +249,20 @@ impl Assembly { return Some(Image { image, offsets }); } // then try cattrs - let offsets_cattrs = MonoClassOffsets::new(module.version, module.pointer_size, true)?; - if process - .read_pointer( - class + offsets_cattrs.monoclassdef_klass + offsets_cattrs.monoclass_image, - module.pointer_size, - ) - .is_ok_and(|a| a == image) - { - return Some(Image { - image, - offsets: offsets_cattrs, - }); + if module.version == Version::V1 { + let offsets_cattrs = MonoClassOffsets::new(Version::V1Cattrs, module.pointer_size)?; + if process + .read_pointer( + class + offsets_cattrs.monoclassdef_klass + offsets_cattrs.monoclass_image, + module.pointer_size, + ) + .is_ok_and(|a| a == image) + { + return Some(Image { + image, + offsets: offsets_cattrs, + }); + } } Some(Image { image, offsets }) } @@ -514,7 +516,7 @@ impl Class { // Mono V1 behaves differently when it comes to recover the static table match module.version { - Version::V1 => Some(vtables + self.offsets.monoclass_vtable_size), + Version::V1 | Version::V1Cattrs => Some(vtables + self.offsets.monoclass_vtable_size), _ => { vtables = vtables + module.offsets.monovtable_vtable; @@ -860,7 +862,7 @@ impl MonoAssemblyOffsets { const fn new(version: Version, pointer_size: PointerSize) -> Option<&'static Self> { match pointer_size { PointerSize::Bit64 => match version { - Version::V1 => Some(&Self { + Version::V1 | Version::V1Cattrs => Some(&Self { monoassembly_aname: 0x10, monoassembly_image: 0x58, monoimage_class_cache: 0x3D0, @@ -898,7 +900,7 @@ impl MonoAssemblyOffsets { }), }, PointerSize::Bit32 => match version { - Version::V1 => Some(&Self { + Version::V1 | Version::V1Cattrs => Some(&Self { monoassembly_aname: 0x8, monoassembly_image: 0x40, monoimage_class_cache: 0x2A0, @@ -944,11 +946,10 @@ impl MonoClassOffsets { const fn new( version: Version, pointer_size: PointerSize, - cattrs: bool, ) -> Option<&'static Self> { match pointer_size { PointerSize::Bit64 => match version { - Version::V1 if cattrs => Some(&Self { + Version::V1Cattrs => Some(&Self { monoclassdef_next_class_cache: 0x108, monoclassdef_klass: 0x0, monoclass_image: 0x48, @@ -998,7 +999,7 @@ impl MonoClassOffsets { }), }, PointerSize::Bit32 => match version { - Version::V1 if cattrs => Some(&Self { + Version::V1Cattrs => Some(&Self { monoclassdef_next_class_cache: 0xAC, monoclassdef_klass: 0x0, monoclass_image: 0x30, @@ -1058,6 +1059,8 @@ impl MonoClassOffsets { pub enum Version { /// Version 1 V1, + /// Version 1 with cattrs + V1Cattrs, /// Version 2 V2, /// Version 3