@@ -22,6 +22,7 @@ namespace Il2CppInterop.Runtime.Injection
2222{
2323 internal static unsafe class InjectorHelpers
2424 {
25+ internal static Assembly Il2CppMscorlib = typeof ( Il2CppSystem . Type ) . Assembly ;
2526 internal static INativeAssemblyStruct InjectedAssembly ;
2627 internal static INativeImageStruct InjectedImage ;
2728 internal static ProcessModule Il2CppModule = Process . GetCurrentProcess ( )
@@ -329,19 +330,52 @@ private static d_ClassFromIl2CppType FindClassFromIl2CppType()
329330 private static d_ClassGetFieldDefaultValue ClassGetFieldDefaultValueDetour = new ( hkClassGetFieldDefaultValue ) ;
330331 internal static d_ClassGetFieldDefaultValue ClassGetFieldDefaultValue ;
331332 internal static d_ClassGetFieldDefaultValue ClassGetFieldDefaultValueOriginal ;
332- private static d_ClassGetFieldDefaultValue FindClassGetFieldDefaultValue ( )
333+ private static d_ClassGetFieldDefaultValue FindClassGetFieldDefaultValue ( bool forceICallMethod = false )
333334 {
334- var getStaticFieldValueAPI = GetIl2CppExport ( nameof ( IL2CPP . il2cpp_field_static_get_value ) ) ;
335- Logger . Instance . LogTrace ( "il2cpp_field_static_get_value: 0x{GetStaticFieldValueApiAddress}" , getStaticFieldValueAPI . ToInt64 ( ) . ToString ( "X2" ) ) ;
335+ // NOTE: In some cases this pointer will be MetadataCache::GetFieldDefaultValueForField due to Field::GetDefaultFieldValue being
336+ // inlined but we'll treat it the same even though it doesn't receive the type parameter the RDX register
337+ // doesn't get cleared so we still get the same parameters
338+ var classGetDefaultFieldValue = IntPtr . Zero ;
336339
337- var getStaticFieldValue = XrefScannerLowLevel . JumpTargets ( getStaticFieldValueAPI ) . Single ( ) ;
338- Logger . Instance . LogTrace ( "Field::StaticGetValue: 0x{GetStaticFieldValueAddress}" , getStaticFieldValue . ToInt64 ( ) . ToString ( "X2" ) ) ;
340+ if ( forceICallMethod )
341+ {
342+ // MonoField isn't present on 2021.2.0+
343+ var monoFieldType = Il2CppMscorlib . GetTypes ( ) . SingleOrDefault ( ( x ) => x . Name is "MonoField" ) ;
344+ if ( monoFieldType == null )
345+ throw new Exception ( $ "Unity { Il2CppInteropRuntime . Instance . UnityVersion } is not supported at the moment: MonoField isn't present in Il2Cppmscorlib.dll for unity version, unable to fetch icall") ;
346+
347+ var monoFieldGetValueInternalThunk = GetIl2CppMethodPointer ( monoFieldType . GetMethod ( nameof ( Il2CppSystem . Reflection . MonoField . GetValueInternal ) ) ) ;
348+ Logger . Instance . LogTrace ( "Il2CppSystem.Reflection.MonoField::thunk_GetValueInternal: 0x{MonoFieldGetValueInternalThunkAddress}" , monoFieldGetValueInternalThunk . ToInt64 ( ) . ToString ( "X2" ) ) ;
349+
350+ var monoFieldGetValueInternal = XrefScannerLowLevel . JumpTargets ( monoFieldGetValueInternalThunk ) . Single ( ) ;
351+ Logger . Instance . LogTrace ( "Il2CppSystem.Reflection.MonoField::GetValueInternal: 0x{MonoFieldGetValueInternalAddress}" , monoFieldGetValueInternal . ToInt64 ( ) . ToString ( "X2" ) ) ;
352+
353+ // Field::GetValueObject could be inlined with Field::GetValueObjectForThread
354+ var fieldGetValueObject = XrefScannerLowLevel . JumpTargets ( monoFieldGetValueInternal ) . Single ( ) ;
355+ Logger . Instance . LogTrace ( "Field::GetValueObject: 0x{FieldGetValueObjectAddress}" , fieldGetValueObject . ToInt64 ( ) . ToString ( "X2" ) ) ;
339356
340- var getStaticFieldValueInternal = XrefScannerLowLevel . JumpTargets ( getStaticFieldValue ) . Last ( ) ;
341- Logger . Instance . LogTrace ( "Field::StaticGetValueInternal : 0x{GetStaticFieldValueInternalAddress }" , getStaticFieldValueInternal . ToInt64 ( ) . ToString ( "X2" ) ) ;
357+ var fieldGetValueObjectForThread = XrefScannerLowLevel . JumpTargets ( fieldGetValueObject ) . Last ( ) ;
358+ Logger . Instance . LogTrace ( "Field::GetValueObjectForThread : 0x{FieldGetValueObjectForThreadAddress }" , fieldGetValueObjectForThread . ToInt64 ( ) . ToString ( "X2" ) ) ;
342359
343- var getStaticFieldValueInternalTargets = XrefScannerLowLevel . JumpTargets ( getStaticFieldValueInternal ) . ToArray ( ) ;
344- var classGetDefaultFieldValue = getStaticFieldValueInternalTargets . Length == 3 ? getStaticFieldValueInternalTargets . Last ( ) : getStaticFieldValueInternalTargets . First ( ) ;
360+ classGetDefaultFieldValue = XrefScannerLowLevel . JumpTargets ( fieldGetValueObjectForThread ) . ElementAt ( 2 ) ;
361+ }
362+ else
363+ {
364+ var getStaticFieldValueAPI = GetIl2CppExport ( nameof ( IL2CPP . il2cpp_field_static_get_value ) ) ;
365+ Logger . Instance . LogTrace ( "il2cpp_field_static_get_value: 0x{GetStaticFieldValueApiAddress}" , getStaticFieldValueAPI . ToInt64 ( ) . ToString ( "X2" ) ) ;
366+
367+ var getStaticFieldValue = XrefScannerLowLevel . JumpTargets ( getStaticFieldValueAPI ) . Single ( ) ;
368+ Logger . Instance . LogTrace ( "Field::StaticGetValue: 0x{GetStaticFieldValueAddress}" , getStaticFieldValue . ToInt64 ( ) . ToString ( "X2" ) ) ;
369+
370+ var getStaticFieldValueInternal = XrefScannerLowLevel . JumpTargets ( getStaticFieldValue ) . Last ( ) ;
371+ Logger . Instance . LogTrace ( "Field::StaticGetValueInternal: 0x{GetStaticFieldValueInternalAddress}" , getStaticFieldValueInternal . ToInt64 ( ) . ToString ( "X2" ) ) ;
372+
373+ var getStaticFieldValueInternalTargets = XrefScannerLowLevel . JumpTargets ( getStaticFieldValueInternal ) . ToArray ( ) ;
374+
375+ if ( getStaticFieldValueInternalTargets . Length == 0 ) return FindClassGetFieldDefaultValue ( true ) ;
376+
377+ classGetDefaultFieldValue = getStaticFieldValueInternalTargets . Length == 3 ? getStaticFieldValueInternalTargets . Last ( ) : getStaticFieldValueInternalTargets . First ( ) ;
378+ }
345379 Logger . Instance . LogTrace ( "Class::GetDefaultFieldValue: 0x{ClassGetDefaultFieldValueAddress}" , classGetDefaultFieldValue . ToInt64 ( ) . ToString ( "X2" ) ) ;
346380
347381 ClassGetFieldDefaultValueOriginal = Detour . Apply ( classGetDefaultFieldValue , ClassGetFieldDefaultValueDetour ) ;
0 commit comments