@@ -461,7 +461,7 @@ impl Class {
461
461
462
462
// Mono V1 behaves differently when it comes to recover the static table
463
463
match module. version {
464
- Version :: V1 => Some ( vtables + module. offsets . monoclass_vtable_size ) ,
464
+ Version :: V1 | Version :: V1Cattrs => Some ( vtables + module. offsets . monoclass_vtable_size ) ,
465
465
_ => {
466
466
vtables = vtables + module. offsets . monovtable_vtable ;
467
467
@@ -743,7 +743,7 @@ struct Offsets {
743
743
monoclass_name_space : u8 ,
744
744
monoclass_fields : u8 ,
745
745
monoclassdef_field_count : u16 ,
746
- monoclass_runtime_info : u8 ,
746
+ monoclass_runtime_info : u16 ,
747
747
monoclass_vtable_size : u8 ,
748
748
monoclass_parent : u8 ,
749
749
monoclassfield_name : u8 ,
@@ -778,6 +778,27 @@ impl Offsets {
778
778
monovtable_vtable : 0x48 ,
779
779
monoclassfieldalignment : 0x20 ,
780
780
} ) ,
781
+ Version :: V1Cattrs => Some ( & Self {
782
+ monoassembly_aname : 0x10 ,
783
+ monoassembly_image : 0x58 ,
784
+ monoimage_class_cache : 0x3D0 ,
785
+ monointernalhashtable_table : 0x20 ,
786
+ monointernalhashtable_size : 0x18 ,
787
+ monoclassdef_next_class_cache : 0x108 ,
788
+ monoclassdef_klass : 0x0 ,
789
+ monoclass_name : 0x50 ,
790
+ monoclass_name_space : 0x58 ,
791
+ monoclass_fields : 0xB0 ,
792
+ monoclassdef_field_count : 0x9C ,
793
+ monoclass_runtime_info : 0x100 ,
794
+ monoclass_vtable_size : 0x18 , // MonoVtable.data
795
+ monoclass_parent : 0x30 ,
796
+ monoclassfield_name : 0x8 ,
797
+ monoclassfield_offset : 0x18 ,
798
+ monoclassruntimeinfo_domain_vtables : 0x8 ,
799
+ monovtable_vtable : 0x48 ,
800
+ monoclassfieldalignment : 0x20 ,
801
+ } ) ,
781
802
Version :: V2 => Some ( & Self {
782
803
monoassembly_aname : 0x10 ,
783
804
monoassembly_image : 0x60 ,
@@ -843,6 +864,27 @@ impl Offsets {
843
864
monovtable_vtable : 0x28 ,
844
865
monoclassfieldalignment : 0x10 ,
845
866
} ) ,
867
+ Version :: V1Cattrs => Some ( & Self {
868
+ monoassembly_aname : 0x8 ,
869
+ monoassembly_image : 0x40 ,
870
+ monoimage_class_cache : 0x2A0 ,
871
+ monointernalhashtable_table : 0x14 ,
872
+ monointernalhashtable_size : 0xC ,
873
+ monoclassdef_next_class_cache : 0xAC ,
874
+ monoclassdef_klass : 0x0 ,
875
+ monoclass_name : 0x34 ,
876
+ monoclass_name_space : 0x38 ,
877
+ monoclass_fields : 0x78 ,
878
+ monoclassdef_field_count : 0x68 ,
879
+ monoclass_runtime_info : 0xA8 ,
880
+ monoclass_vtable_size : 0xC , // MonoVtable.data
881
+ monoclass_parent : 0x24 ,
882
+ monoclassfield_name : 0x4 ,
883
+ monoclassfield_offset : 0xC ,
884
+ monoclassruntimeinfo_domain_vtables : 0x4 ,
885
+ monovtable_vtable : 0x28 ,
886
+ monoclassfieldalignment : 0x10 ,
887
+ } ) ,
846
888
Version :: V2 => Some ( & Self {
847
889
monoassembly_aname : 0x8 ,
848
890
monoassembly_image : 0x44 ,
@@ -897,6 +939,8 @@ impl Offsets {
897
939
pub enum Version {
898
940
/// Version 1
899
941
V1 ,
942
+ /// Version 1 with cattrs
943
+ V1Cattrs ,
900
944
/// Version 2
901
945
V2 ,
902
946
/// Version 3
@@ -905,7 +949,27 @@ pub enum Version {
905
949
906
950
fn detect_version ( process : & Process ) -> Option < Version > {
907
951
if process. get_module_address ( "mono.dll" ) . is_ok ( ) {
908
- return Some ( Version :: V1 ) ;
952
+ // If the module mono.dll is present, then it's either V1 or V1Cattrs.
953
+ // In order to distinguish between them, we check the first class listed in the
954
+ // default Assembly-CSharp image and check for the pointer to its name, assuming it's using V1.
955
+ // If such pointer matches the address to the assembly image instead, then it's V1Cattrs.
956
+ // The idea is taken from https://github.com/Voxelse/Voxif/blob/main/Voxif.Helpers/Voxif.Helpers.UnityHelper/UnityHelper.cs#L343-L344
957
+ let module = Module :: attach ( process, Version :: V1 ) ?;
958
+ let image = module. get_default_image ( process) ?;
959
+ let class = image. classes ( process, & module) . next ( ) ?;
960
+
961
+ let pointer_to_image = process
962
+ . read_pointer (
963
+ class. class + module. offsets . monoclass_name ,
964
+ module. pointer_size ,
965
+ )
966
+ . ok ( ) ?;
967
+
968
+ return Some ( if pointer_to_image. eq ( & image. image ) {
969
+ Version :: V1Cattrs
970
+ } else {
971
+ Version :: V1
972
+ } ) ;
909
973
}
910
974
911
975
let unity_module = {
0 commit comments