public static IntPtr ResolveICall(string signature) { MelonDebug.Msg("Resolving ICall " + signature); IntPtr icallPtr; if (MelonUtils.IsGameIl2Cpp()) { icallPtr = il2cpp_resolve_icall(signature); } else { // We generate a fake MonoMethod + MonoMethodSignature + MonoClass struct to exploit the lookup code and force resolve our icall without the class/method being registered // (Slaynash: Yes this is illegal) MonoMethod *monoMethod = IcallToFakeMonoMethod(signature); icallPtr = mono_lookup_internal_call((IntPtr)monoMethod); DestroyFakeMonoMethod(monoMethod); } if (icallPtr == IntPtr.Zero) { //MelonLogger.Error($"ICall {signature} not resolved"); //return IntPtr.Zero; throw new Exception($"ICall {signature} not resolved"); } MelonDebug.Msg($" > 0x{(long)icallPtr:X}"); return(icallPtr); }
private static unsafe void DestroyFakeMonoMethod(MonoMethod *monoMethod) { Marshal.FreeHGlobal((IntPtr)monoMethod->signature); Marshal.FreeHGlobal(*(IntPtr *)((long)&monoMethod->klass->nested_in_0x04 + monoClassOffset)); Marshal.FreeHGlobal(*(IntPtr *)((long)&monoMethod->klass->nested_in_0x08 + monoClassOffset)); Marshal.FreeHGlobal((IntPtr)monoMethod->klass); Marshal.FreeHGlobal((IntPtr)monoMethod->name); Marshal.FreeHGlobal((IntPtr)monoMethod); }
private static unsafe MonoMethod *IcallToFakeMonoMethod(string icallName) { string[] typeAndMethod = icallName.Split(new[] { "::" }, StringSplitOptions.None); int parenthesisIndex = typeAndMethod[1].IndexOf('('); if (parenthesisIndex >= 0) { typeAndMethod[1] = typeAndMethod[1].Substring(0, parenthesisIndex); } // We add a padding to the end of each allocated memory since our structs are supposed to be bigger than the one we have here MonoMethod *monoMethod = (MonoMethod *)Marshal.AllocHGlobal(sizeof(MonoMethod) + 0x100); monoMethod->applyZeroes(); monoMethod->klass = (MonoClass *)Marshal.AllocHGlobal(sizeof(MonoClass) + 0x100); monoMethod->klass->applyZeroes(); monoMethod->name = (byte *)Marshal.StringToHGlobalAnsi(typeAndMethod[1]); int lastDotIndex = typeAndMethod[0].LastIndexOf('.'); if (lastDotIndex < 0) { *(IntPtr *)((long)&monoMethod->klass->nested_in_0x08 + monoClassOffset) = Marshal.StringToHGlobalAnsi(""); *(IntPtr *)((long)&monoMethod->klass->nested_in_0x04 + monoClassOffset) = Marshal.StringToHGlobalAnsi(typeAndMethod[0]); } else { string name_space = typeAndMethod[0].Substring(0, lastDotIndex); string name = typeAndMethod[0].Substring(lastDotIndex + 1); *(IntPtr *)((long)&monoMethod->klass->nested_in_0x08 + monoClassOffset) = Marshal.StringToHGlobalAnsi(name_space); *(IntPtr *)((long)&monoMethod->klass->nested_in_0x04 + monoClassOffset) = Marshal.StringToHGlobalAnsi(name); } MonoMethodSignature *monoMethodSignature = (MonoMethodSignature *)Marshal.AllocHGlobal(sizeof(MonoMethodSignature)); monoMethodSignature->ApplyZeroes(); monoMethod->signature = monoMethodSignature; return(monoMethod); }