diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..ccbf606 --- /dev/null +++ b/Config.cs @@ -0,0 +1,35 @@ +using BepInEx.Configuration; + +namespace undead_universal_patch_il2cpp +{ + public static class GenericConfig + { + public static ConfigEntry LogAllRequests; + } + public static class GenericConfigDefaults + { + public static bool LogAllRequests = false; + } + public static class NameserverConfig + { + public static ConfigEntry Rewrite; + public static ConfigEntry NewUrl; + } + public static class NameserverConfigDefaults + { + public static bool Rewrite = false; + public static string NewUrl = "https://example.com/nameserver"; + } + public static class PhotonConfig + { + public static ConfigEntry PatchPhotonIds; + public static ConfigEntry AppID; + public static ConfigEntry VoiceAppID; + } + public static class PhotonConfigDefaults + { + public static bool PatchPhotonIds = false; + public static string AppID = "replace-me-please"; + public static string VoiceAppID = "replace-me-please"; + } +} diff --git a/Patches/BestHTTP.cs b/Patches/BestHTTP.cs new file mode 100644 index 0000000..96af726 --- /dev/null +++ b/Patches/BestHTTP.cs @@ -0,0 +1,66 @@ +using System; +using System.Reflection; +using HarmonyLib; + +namespace undead_universal_patch_il2cpp.Patches +{ + [HarmonyPatch] + public class BestHTTP_Unob + { + static string TargetTypeName = "BestHTTP.HTTPManager"; + static string TargetMethodName = "SendRequest"; + static string Description = "Unobfuscated BestHTTP request URL rewrite patch"; + static readonly Type targetType = AccessTools.TypeByName(TargetTypeName); + static readonly Type requestType = AccessTools.TypeByName("BestHTTP.HTTPRequest"); + static readonly MethodInfo targetMethod = AccessTools.Method(targetType, TargetMethodName, [requestType]); + + static bool Prepare() + { + if (targetType == null) + { + Plugin.Log.LogWarning($"'{Description}' disabled. The type for this patch was not found."); + return false; + } + if (targetMethod == null) + { + Plugin.Log.LogWarning($"'{Description}' disabled. The method for this patch was not found."); + return false; + } + + Plugin.Log.LogInfo($"'{Description}' succeeded validation."); + return true; + } + + static MethodBase TargetMethod() + { + return targetMethod; + } + + [HarmonyPrefix] + static bool Prefix(ref object request) + { + PropertyInfo uriProperty = AccessTools.Property(requestType, "Uri"); + if (uriProperty == null) + { + Plugin.Log.LogFatal("BestHTTP_Unob failed: uriProperty was null."); + return false; + } + + var uriInstance = (Uri)uriProperty.GetValue(request, null); + if (uriInstance == null) + { + Plugin.Log.LogFatal("BestHTTP_Unob failed: uriInstance was null."); + return false; + } + + if (GenericConfig.LogAllRequests.Value) Plugin.Log.LogInfo($"BestHTTP_Unob request (Before) URL: {uriInstance.ToString()}"); + + Uri newUri = new(NameserverConfig.NewUrl.Value); + + if (GenericConfig.LogAllRequests.Value) Plugin.Log.LogInfo($"BestHTTP_Unob request (After) URL: {newUri.ToString()}"); + + uriProperty.SetValue(request, NameserverConfig., null); + return true; + } + } +} diff --git a/Patches/Photon.cs b/Patches/Photon.cs new file mode 100644 index 0000000..680d184 --- /dev/null +++ b/Patches/Photon.cs @@ -0,0 +1,94 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace undead_universal_patch_il2cpp.Patches +{ + public class PhotonPatchEvent + { + + } + + public class Photon + { + public static object Patch() + { + Plugin.Log.LogInfo("Attempting Photon patch."); + Type serverSettingsType = AccessTools.TypeByName("ServerSettings"); + + Type hostingOptionType = AccessTools.Inner(serverSettingsType, "HostingOption"); + if (serverSettingsType == null) + { + Plugin.Log.LogFatal("Photon patch failed early, this Photon client is unsupported!"); + return null; + } + + ScriptableObject settingsInstance = ScriptableObject.CreateInstance(serverSettingsType); + + object realPhotonServerSettings = Resources.Load("PhotonServerSettings", serverSettingsType); + + try + { + var rpcListField = AccessTools.Field(serverSettingsType, "RpcList"); + if (rpcListField == null) + { + Plugin.Log.LogFatal("Photon patch failed (serverSettingsType did not have an RpcList), this Photon client is unsupported!"); + return null; + } + if (realPhotonServerSettings == null) + { + Plugin.Log.LogFatal("Photon patch failed (existing photon settings was null, is the patch event set to 'Awake'?), this Photon client is unsupported!"); + return null; + } + var existingRpcList = (List)rpcListField.GetValue(realPhotonServerSettings); + rpcListField.SetValue(settingsInstance, existingRpcList); + } + catch (Exception e) + { + Plugin.Log.LogFatal("Photon patch failed (RpcList), this Photon client is unsupported!"); + Plugin.Log.LogDebug(e); + return null; + } + + var appIdField = AccessTools.Field(serverSettingsType, "AppID"); + appIdField.SetValue(settingsInstance, PhotonConfig.AppID.Value); + var voiceAppIdField = AccessTools.Field(serverSettingsType, "VoiceAppID"); + voiceAppIdField.SetValue(settingsInstance, PhotonConfig.VoiceAppID.Value); + + var hostTypeField = AccessTools.Field(serverSettingsType, "HostType"); + if (hostTypeField != null && hostingOptionType != null && hostingOptionType.IsEnum) + { + try + { + object enumValue = Enum.Parse(hostingOptionType, "PhotonCloud"); + hostTypeField.SetValue(settingsInstance, enumValue); + } + catch (ArgumentException ex) + { + Plugin.Log.LogFatal($"Photon patch failed, cannot set HostingOption: {ex.Message}"); + return null; + } + } + + // Save to property + Type photonNetworkType = AccessTools.TypeByName("PhotonNetwork"); + if (photonNetworkType == null) + { + Plugin.Log.LogFatal("Photon patch will not work (class not found). Is this build supported?"); + return null; + } + FieldInfo photonServerSettingsField = photonNetworkType.GetField("PhotonServerSettings"); + if (photonServerSettingsField == null) + { + Plugin.Log.LogFatal("Photon patch will not work (property not found). Is this build supported?"); + return null; + } + photonServerSettingsField.SetValue(serverSettingsType, settingsInstance); + + Plugin.Log.LogInfo("Photon patch was successful."); + return settingsInstance; + } + } +} diff --git a/Plugin.cs b/Plugin.cs new file mode 100644 index 0000000..79eb4e3 --- /dev/null +++ b/Plugin.cs @@ -0,0 +1,40 @@ +using BepInEx; +using BepInEx.Logging; +using BepInEx.Unity.IL2CPP; +using HarmonyLib; + +namespace undead_universal_patch_il2cpp; + +[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "1.0.0")] +public class Plugin : BasePlugin +{ + public static new readonly ManualLogSource Log = Logger.CreateLogSource("UUPatch"); + + public static Harmony _hi = new("dev.proxnet.recroom.universalpatch.noneac.il2cpp"); + + public override bool Unload() + { + Log.LogInfo("Destroying."); + _hi.UnpatchSelf(); + return true; + } + + public override void Load() + { + GenericConfig.LogAllRequests = Config.Bind("Generic", "LogAllRequests", GenericConfigDefaults.LogAllRequests, + "Log all HTTP requests sent by the game."); + PhotonConfig.PatchPhotonIds = Config.Bind("Photon", "PatchPhotonIds", PhotonConfigDefaults.PatchPhotonIds, + "Enable/disable changing the target IDs in PhotonServerSettings." + + "\nCustom server settings are not yet supported."); + PhotonConfig.AppID = Config.Bind("Photon", "AppID", PhotonConfigDefaults.AppID, + "The new target (PUN) App ID from the Photon dashboard."); + PhotonConfig.VoiceAppID = Config.Bind("Photon", "VoiceAppID", PhotonConfigDefaults.VoiceAppID, + "The new target Voice App ID from the Photon dashboard."); + NameserverConfig.Rewrite = Config.Bind("Nameserver", "Rewrite", NameserverConfigDefaults.Rewrite, + "Enable/disable rewriting the URL for nameserver requests."); + NameserverConfig.NewUrl = Config.Bind("Nameserver", "NewUrl", NameserverConfigDefaults.NewUrl, + "The new full URL to use when sending a nameserver request."); + + _hi.PatchAll(); + } +} \ No newline at end of file diff --git a/undead-universal-patch-il2cpp.csproj b/undead-universal-patch-il2cpp.csproj new file mode 100644 index 0000000..c81600e --- /dev/null +++ b/undead-universal-patch-il2cpp.csproj @@ -0,0 +1,37 @@ + + + + net6.0 + undead_universal_patch_il2cpp + My first plugin + 1.0.0 + true + latest + + https://api.nuget.org/v3/index.json; + https://nuget.bepinex.dev/v3/index.json; + https://nuget.samboy.dev/v3/index.json + + undead_universal_patch_il2cpp + + + + + + + + + + G:\rr\2019-10-25 (5120486837419374208)\BepInEx\interop\Assembly-CSharp.dll + + + G:\rr\2019-10-25 (5120486837419374208)\BepInEx\interop\Il2Cppmscorlib.dll + + + G:\rr\2019-10-25 (5120486837419374208)\cpp2il_out\UnityEngine.dll + + + G:\rr\2019-10-25 (5120486837419374208)\cpp2il_out\UnityEngine.CoreModule.dll + + + diff --git a/undead-universal-patch-il2cpp.sln b/undead-universal-patch-il2cpp.sln new file mode 100644 index 0000000..5159135 --- /dev/null +++ b/undead-universal-patch-il2cpp.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "undead-universal-patch-il2cpp", "undead-universal-patch-il2cpp.csproj", "{EA77CD32-EB68-4D7D-96B2-644785D96DEA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA77CD32-EB68-4D7D-96B2-644785D96DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA77CD32-EB68-4D7D-96B2-644785D96DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA77CD32-EB68-4D7D-96B2-644785D96DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA77CD32-EB68-4D7D-96B2-644785D96DEA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0BAB65B6-7962-4D94-92F2-9BD2B35DAAA9} + EndGlobalSection +EndGlobal