using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CroatiaUtils.Extensions;
using CroatiaUtils.Imports;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.FieldInfo;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Type;
using Microsoft.CodeAnalysis;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("VaigaLegaAPI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("VaigaLegaAPI")]
[assembly: AssemblyTitle("VaigaLegaAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NativeIntegerAttribute : Attribute
{
public readonly bool[] TransformFlags;
public NativeIntegerAttribute()
{
TransformFlags = new bool[1] { true };
}
public NativeIntegerAttribute(bool[] P_0)
{
TransformFlags = P_0;
}
}
}
namespace CroatiaUtils
{
internal static class CroatiaLogger
{
private static ManualLogSource m_LogSource;
public static void SetupFromInit(ManualLogSource logSource)
{
m_LogSource = logSource;
}
private static string Format(object data)
{
return data.ToString();
}
public static void Debug(object msg)
{
m_LogSource.LogDebug((object)Format(msg));
}
public static void Info(object msg)
{
m_LogSource.LogInfo((object)Format(msg));
}
public static void Message(object msg)
{
m_LogSource.LogMessage((object)Format(msg));
}
public static void Warn(object msg)
{
m_LogSource.LogWarning((object)Format(msg));
}
public static void Error(object msg)
{
m_LogSource.LogError((object)Format(msg));
}
public static void Fatal(object msg)
{
m_LogSource.LogFatal((object)Format(msg));
}
}
[BepInPlugin("com.kasuromi.croatiautils", "CroatiaUtils", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class EntryPoint : BasePlugin
{
public override void Load()
{
if (new StackTrace().GetFrame(1).GetMethod().DeclaringType.Assembly != typeof(IL2CPPChainloader).Assembly)
{
Environment.FailFast("VAIGA LEGA KASUROM!!! 2 FATHER");
throw null;
}
CroatiaLogger.SetupFromInit(((BasePlugin)this).Log);
}
}
public static class Il2CppUtils
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static INativeClassStruct GetClass<TClass>()
{
return Il2CppClassPointerStore<TClass>.NativeClassPtr.AsIl2CppClass();
}
public unsafe static void AddField(IntPtr classPointer, IntPtr fieldTypeClassPointer, string fieldName)
{
INativeClassStruct val = classPointer.AsIl2CppClass();
INativeClassStruct val2 = fieldTypeClassPointer.AsIl2CppClass();
INativeFieldInfoStruct val3 = UnityVersionHandler.NewField();
val3.Name = Marshal.StringToHGlobalAnsi(fieldName);
val3.Type = (val2.ValueType ? val2.ByValArg.TypePointer : val2.ThisArg.TypePointer);
val3.Parent = val.ClassPointer;
uint num = 0u;
uint num2 = (uint)(val2.ValueType ? IL2CPP.il2cpp_class_value_size(((INativeStruct)val2).Pointer, ref num) : sizeof(void*));
val3.Offset = (int)val.InstanceSize;
val.ActualSize += num2;
val.InstanceSize += num2;
nint num3 = Marshal.AllocHGlobal((val.FieldCount + 1) * UnityVersionHandler.FieldInfoSize());
num = 0u;
IEnumerable<INativeFieldInfoStruct> enumerable = val.GetFields().ToArray();
foreach (INativeFieldInfoStruct item in enumerable)
{
Unsafe.CopyBlock((void*)(num3 + (nint)(num * UnityVersionHandler.FieldInfoSize())), (void*)((INativeStruct)item).Pointer, (uint)UnityVersionHandler.FieldInfoSize());
num++;
}
Unsafe.CopyBlock((void*)(num3 + (nint)(num * UnityVersionHandler.FieldInfoSize())), (void*)((INativeStruct)val3).Pointer, (uint)UnityVersionHandler.FieldInfoSize());
Marshal.FreeHGlobal(((INativeStruct)val3).Pointer);
val.Fields = (Il2CppFieldInfo*)(void*)(IntPtr)num3;
val.FieldCount++;
foreach (INativeFieldInfoStruct item2 in enumerable)
{
IL2CPP.il2cpp_free(((INativeStruct)item2).Pointer);
}
}
}
public struct MemoryProtectionCookie : IDisposable
{
private Kernel32.MemoryProtectionConstant m_OldProtection;
private readonly nint m_Address;
private readonly nint m_Size;
public MemoryProtectionCookie(nint address, Kernel32.MemoryProtectionConstant newProtection, nint size = 16)
{
m_Address = address;
m_Size = size;
if (!Kernel32.VirtualProtect(m_Address, m_Size, newProtection, out m_OldProtection))
{
Environment.FailFast($"Failed to protect address 0x{m_Address:X2} with protection {newProtection}");
}
CroatiaLogger.Debug($"MemoryProtectionCookie: Modified protection of address 0x{m_Address:X2} from {m_OldProtection} to {newProtection}");
}
public void Dispose()
{
Kernel32.MemoryProtectionConstant oldProtection = m_OldProtection;
if (!Kernel32.VirtualProtect(m_Address, m_Size, m_OldProtection, out m_OldProtection))
{
Environment.FailFast($"Failed to revert memory protection of address 0x{m_Address:X2}");
}
CroatiaLogger.Debug($"MemoryProtectionCookie: Reverted protection of address 0x{m_Address:X2} to {oldProtection}");
}
}
public static class MemoryUtils
{
private unsafe delegate void* d_FindSignatureInBlock(void* block, ulong blockSize, string pattern, string mask, ulong sigOffset);
private static readonly byte[] s_TrampolineShellcode = new byte[12]
{
72, 184, 0, 0, 0, 0, 0, 0, 0, 0,
255, 224
};
private static readonly Type s_MemoryUtilsType = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins["dev.gtfomodding.gtfo-api"].Instance.GetType().Assembly.GetType("GTFO.API.Utilities.MemoryUtils");
private static d_FindSignatureInBlock fnFindSignatureInBlock;
public unsafe static byte[] MakeTrampoline(nint destination)
{
byte[] array = new byte[s_TrampolineShellcode.Length];
Array.Copy(s_TrampolineShellcode, 0, array, 0, s_TrampolineShellcode.Length);
fixed (byte* ptr = array)
{
*(long*)(ptr + 2) = destination;
}
return array;
}
public unsafe static void CreateTrampolineBetween(nint start, nint end, nint destination)
{
nint num = end - start;
if (num < s_TrampolineShellcode.Length)
{
throw new Exception("Trampoline block size is not enough to create.");
}
using (new MemoryProtectionCookie(start, Kernel32.MemoryProtectionConstant.ExecuteReadWrite, num))
{
CroatiaLogger.Debug("NOPing trampoline section");
for (nint num2 = 0; num2 < num; num2++)
{
*(sbyte*)(start + num2) = -112;
}
CroatiaLogger.Debug("Creating trampoline shellcode");
byte[] array = MakeTrampoline(destination);
CroatiaLogger.Debug("Writing shellcode to trampoline section");
Unsafe.CopyBlock((void*)start, Unsafe.AsPointer(ref array[0]), (uint)array.Length);
}
}
public unsafe static nint FindSignatureInBlock(nint block, ulong blockSize, string pattern, string mask, ulong sigOffset = 0uL)
{
if (fnFindSignatureInBlock == null)
{
fnFindSignatureInBlock = AccessTools.MethodDelegate<d_FindSignatureInBlock>(AccessTools.Method(s_MemoryUtilsType, "FindSignatureInBlock", new Type[5]
{
typeof(void*),
typeof(ulong),
typeof(string),
typeof(string),
typeof(ulong)
}, (Type[])null), (object)null, true);
}
return (nint)fnFindSignatureInBlock((void*)block, blockSize, pattern, mask, sigOffset);
}
}
[GeneratedCode("VersionInfoGenerator", "2.0.0+git50a4b1a-master")]
[CompilerGenerated]
internal static class VersionInfo
{
public const string RootNamespace = "CroatiaUtils";
public const string Version = "1.0.0";
public const string VersionPrerelease = null;
public const string VersionMetadata = null;
public const string SemVer = "1.0.0";
public const string GitRevShort = null;
public const string GitRevLong = null;
public const string GitBranch = null;
public const string GitTag = null;
public const bool GitIsDirty = false;
}
}
namespace CroatiaUtils.Imports
{
public static class Kernel32
{
[Flags]
public enum MemoryAllocationConstant : uint
{
Commit = 0x1000u,
Reserve = 0x2000u,
Reset = 0x80000u,
ResetUndo = 0x1000000u,
LargePages = 0x20000000u,
Physical = 0x400000u,
TopDown = 0x100000u,
WriteWatch = 0x200000u
}
[Flags]
public enum MemoryProtectionConstant : uint
{
NoAccess = 1u,
ReadOnly = 2u,
ReadWrite = 4u,
WriteCopy = 8u,
Execute = 0x10u,
ExecuteRead = 0x20u,
ExecuteReadWrite = 0x40u,
ExecuteWriteCopy = 0x80u
}
[DllImport("kernel32.dll")]
public static extern nint VirtualAlloc(nint lpAddress, nint dwSize, MemoryAllocationConstant flAllocationType, MemoryProtectionConstant flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(nint lpAddress, nint dwSize, MemoryProtectionConstant flNewProtect, out MemoryProtectionConstant lpflOldProtect);
}
}
namespace CroatiaUtils.Extensions
{
public static class ArrayExtensions
{
public static void ShuffleWithRandom<T>(this T[] array, Random rngProvider)
{
for (int i = 0; i < array.Length; i++)
{
int num = rngProvider.Next(0, array.Length);
int num2 = i;
int num3 = num;
T val = array[num];
T val2 = array[i];
array[num2] = val;
array[num3] = val2;
}
}
}
public static class INativeClassStructExtensions
{
public static IEnumerable<INativeMethodInfoStruct> GetMethods(this INativeClassStruct nativeClassStruct)
{
for (int i = 0; i < nativeClassStruct.MethodCount; i++)
{
yield return nativeClassStruct.GetMethod(i);
}
}
public static IEnumerable<INativeFieldInfoStruct> GetFields(this INativeClassStruct nativeClassStruct)
{
for (int i = 0; i < nativeClassStruct.FieldCount; i++)
{
yield return nativeClassStruct.GetField(i);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public unsafe static INativeMethodInfoStruct GetMethod(this INativeClassStruct il2cppClass, int idx)
{
return UnityVersionHandler.Wrap(il2cppClass.Methods[idx]);
}
public static INativeMethodInfoStruct? GetMethod(this INativeClassStruct il2cppClass, string name)
{
return il2cppClass.GetMethods().FirstOrDefault((Func<INativeMethodInfoStruct, bool>)((INativeMethodInfoStruct x) => Marshal.PtrToStringUTF8(x.Name) == name));
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public unsafe static INativeFieldInfoStruct GetField(this INativeClassStruct il2cppClass, int idx)
{
return ((nint)((byte*)il2cppClass.Fields + idx * UnityVersionHandler.FieldInfoSize())).AsIl2CppFieldInfo();
}
}
public static class IntPtrExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public unsafe static INativeClassStruct AsIl2CppClass(this IntPtr ptr)
{
return UnityVersionHandler.Wrap((Il2CppClass*)(void*)ptr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public unsafe static INativeTypeStruct AsIl2CppType(this IntPtr ptr)
{
return UnityVersionHandler.Wrap((Il2CppTypeStruct*)(void*)ptr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public unsafe static INativeFieldInfoStruct AsIl2CppFieldInfo(this IntPtr ptr)
{
return UnityVersionHandler.Wrap((Il2CppFieldInfo*)(void*)ptr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public unsafe static INativeMethodInfoStruct AsIl2CppMethodInfo(this IntPtr ptr)
{
return UnityVersionHandler.Wrap((Il2CppMethodInfo*)(void*)ptr);
}
}
public static class TypeExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static IntPtr GetIl2CppClassPointer(this Type type)
{
return Il2CppClassPointerStore.GetNativeClassPointer(type);
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static INativeClassStruct GetIl2CppClass(this Type type)
{
return type.GetIl2CppClassPointer().AsIl2CppClass();
}
}
}