Initial commit
This commit is contained in:
@@ -5,10 +5,14 @@ namespace undead_universal_patch_il2cpp
|
|||||||
public static class GenericConfig
|
public static class GenericConfig
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> LogAllRequests;
|
public static ConfigEntry<bool> LogAllRequests;
|
||||||
|
public static ConfigEntry<bool> CertificatePatch;
|
||||||
|
public static ConfigEntry<bool> HilePatch;
|
||||||
}
|
}
|
||||||
public static class GenericConfigDefaults
|
public static class GenericConfigDefaults
|
||||||
{
|
{
|
||||||
public static bool LogAllRequests = false;
|
public static bool LogAllRequests = false;
|
||||||
|
public static bool CertificatePatch = false;
|
||||||
|
public static bool HilePatch = false;
|
||||||
}
|
}
|
||||||
public static class NameserverConfig
|
public static class NameserverConfig
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) [year] [fullname]
|
Copyright (c) 2024 proxnet.dev
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
@@ -31,10 +31,7 @@ namespace undead_universal_patch_il2cpp.Patches
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MethodBase TargetMethod()
|
static MethodBase TargetMethod() => targetMethod;
|
||||||
{
|
|
||||||
return targetMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
static bool Prefix(ref object request)
|
static bool Prefix(ref object request)
|
||||||
@@ -46,7 +43,7 @@ namespace undead_universal_patch_il2cpp.Patches
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var uriInstance = (Uri)uriProperty.GetValue(request, null);
|
var uriInstance = (Il2CppSystem.Uri)uriProperty.GetValue(request, null);
|
||||||
if (uriInstance == null)
|
if (uriInstance == null)
|
||||||
{
|
{
|
||||||
Plugin.Log.LogFatal("BestHTTP_Unob failed: uriInstance was null.");
|
Plugin.Log.LogFatal("BestHTTP_Unob failed: uriInstance was null.");
|
||||||
@@ -55,11 +52,11 @@ namespace undead_universal_patch_il2cpp.Patches
|
|||||||
|
|
||||||
if (GenericConfig.LogAllRequests.Value) Plugin.Log.LogInfo($"BestHTTP_Unob request (Before) URL: {uriInstance.ToString()}");
|
if (GenericConfig.LogAllRequests.Value) Plugin.Log.LogInfo($"BestHTTP_Unob request (Before) URL: {uriInstance.ToString()}");
|
||||||
|
|
||||||
Uri newUri = new(NameserverConfig.NewUrl.Value);
|
Il2CppSystem.Uri newUri = new(uriInstance.ToString().Contains("ns.rec.net") ? NameserverConfig.NewUrl.Value : uriInstance.ToString());
|
||||||
|
|
||||||
if (GenericConfig.LogAllRequests.Value) Plugin.Log.LogInfo($"BestHTTP_Unob request (After) URL: {newUri.ToString()}");
|
if (GenericConfig.LogAllRequests.Value) Plugin.Log.LogInfo($"BestHTTP_Unob request (After) URL: {newUri.ToString()}");
|
||||||
|
|
||||||
uriProperty.SetValue(request, NameserverConfig., null);
|
uriProperty.SetValue(request, NameserverConfig.Rewrite.Value ? newUri : uriInstance, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
63
Patches/HilePatch.cs
Normal file
63
Patches/HilePatch.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace undead_universal_patch_il2cpp.Patches
|
||||||
|
{
|
||||||
|
[HarmonyPatch]
|
||||||
|
public static class HilePatch
|
||||||
|
{
|
||||||
|
public static void Patch()
|
||||||
|
{
|
||||||
|
Plugin.Log.LogInfo("Attempting hile patch");
|
||||||
|
|
||||||
|
HileManager man = GameObject.Find("/GameRoot/Startup/Core Systems/[CheatManager]").GetComponent<HileManager>();
|
||||||
|
|
||||||
|
string[] asdf = [
|
||||||
|
"GameAssembly.dll",
|
||||||
|
"UnityPlayer.dll",
|
||||||
|
"WinPixEventRuntime.dll",
|
||||||
|
"steam_api64.dll",
|
||||||
|
"steam_api.dll",
|
||||||
|
"d3d11.dll",
|
||||||
|
"d3d9.dll",
|
||||||
|
"d3d8.dll",
|
||||||
|
"ddraw.dll",
|
||||||
|
"dxgi.dll",
|
||||||
|
"winhttp.dll"
|
||||||
|
];
|
||||||
|
man.KnownDlls = asdf;
|
||||||
|
|
||||||
|
Plugin.Log.LogInfo("Hile patch successful.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static string TargetTypeName = "BootSequence";
|
||||||
|
static string TargetMethodName = "set_CurrentState";
|
||||||
|
static string Description = "Add BepInEx to allowed DLLs";
|
||||||
|
static Type targetType = AccessTools.TypeByName(TargetTypeName);
|
||||||
|
static MethodInfo targetMethod = AccessTools.Method(targetType, TargetMethodName);
|
||||||
|
|
||||||
|
static bool Prepare()
|
||||||
|
{
|
||||||
|
if (targetMethod == null)
|
||||||
|
{
|
||||||
|
Plugin.Log.LogWarning($"'{Description}' disabled. The type for this patch was not found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.Log.LogInfo($"'{Description}' succeeded validation.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodBase TargetMethod()
|
||||||
|
{
|
||||||
|
return targetMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Prefix(ref BootSequence __instance)
|
||||||
|
{
|
||||||
|
if (GenericConfig.HilePatch.Value && __instance.CurrentState == BootSequence.BootSequenceState.RECNET_CONNECTION) Patch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using Il2CppInterop.Runtime;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -6,89 +7,44 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace undead_universal_patch_il2cpp.Patches
|
namespace undead_universal_patch_il2cpp.Patches
|
||||||
{
|
{
|
||||||
|
[HarmonyPatch]
|
||||||
public class PhotonPatchEvent
|
public class PhotonPatchEvent
|
||||||
{
|
{
|
||||||
|
static readonly string TargetTypeName = "RecNet.Core";
|
||||||
|
static readonly string TargetMethodName = "ConnectToRecNet";
|
||||||
|
static readonly string Description = "Photon Patch event method";
|
||||||
|
static readonly MethodInfo connectMethod = AccessTools.Method(AccessTools.TypeByName(TargetTypeName), TargetMethodName);
|
||||||
|
|
||||||
|
static bool Prepare()
|
||||||
|
{
|
||||||
|
if (connectMethod == null)
|
||||||
|
{
|
||||||
|
Plugin.Log.LogWarning($"'{Description}' disabled. The type for this patch was not found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.Log.LogInfo($"'{Description}' succeeded validation.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static MethodBase TargetMethod() => connectMethod;
|
||||||
|
static void Prefix()
|
||||||
|
{
|
||||||
|
if (PhotonConfig.PatchPhotonIds.Value) Photon.Patch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Photon
|
public class Photon
|
||||||
{
|
{
|
||||||
public static object Patch()
|
public static void Patch()
|
||||||
{
|
{
|
||||||
Plugin.Log.LogInfo("Attempting Photon patch.");
|
/*
|
||||||
Type serverSettingsType = AccessTools.TypeByName("ServerSettings");
|
Normally, I would be using reflection and AccessTools to create a new instance of ServerSettings and set the value of PhotonNetwork.PhotonServerSettings,
|
||||||
|
but since it was difficult and confusing with IL2CPP, I ended up just using explicit references.. every targeted game build *should* have these types anyway.
|
||||||
|
Now I'm wondering if the patch runs faster when using explicit references rather than reflection
|
||||||
|
*/
|
||||||
|
|
||||||
Type hostingOptionType = AccessTools.Inner(serverSettingsType, "HostingOption");
|
PhotonNetwork.PhotonServerSettings.AppID = PhotonConfig.AppID.Value;
|
||||||
if (serverSettingsType == null)
|
PhotonNetwork.PhotonServerSettings.VoiceAppID = PhotonConfig.VoiceAppID.Value;
|
||||||
{
|
|
||||||
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<string>)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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
Patches/RealPhotonPatchEvent.cs
Normal file
15
Patches/RealPhotonPatchEvent.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using ExitGames.Client.Photon;
|
||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace undead_universal_patch_il2cpp.Patches
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(PhotonNetwork), nameof(PhotonNetwork.ConnectUsingSettings))]
|
||||||
|
public class RealPhotonPatchEvent
|
||||||
|
{
|
||||||
|
public static void Prefix()
|
||||||
|
{
|
||||||
|
Photon.Patch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
Patches/TLS.cs
Normal file
41
Patches/TLS.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace undead_universal_patch_il2cpp.Patches
|
||||||
|
{
|
||||||
|
[HarmonyPatch]
|
||||||
|
public class TLSPatch
|
||||||
|
{
|
||||||
|
static string TargetTypeName = "Org.BouncyCastle.Crypto.Tls.LegacyTlsAuthentication";
|
||||||
|
static string TargetMethodName = "NotifyServerCertificate";
|
||||||
|
static string Description = "Certificate patch";
|
||||||
|
static Type targetType = AccessTools.TypeByName(TargetTypeName);
|
||||||
|
static MethodInfo targetMethod = AccessTools.Method(targetType, TargetMethodName);
|
||||||
|
|
||||||
|
static bool Prepare()
|
||||||
|
{
|
||||||
|
if (targetMethod == 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() => targetMethod;
|
||||||
|
|
||||||
|
static bool Prefix()
|
||||||
|
{
|
||||||
|
return !(GenericConfig.CertificatePatch.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ namespace undead_universal_patch_il2cpp;
|
|||||||
[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "1.0.0")]
|
[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "1.0.0")]
|
||||||
public class Plugin : BasePlugin
|
public class Plugin : BasePlugin
|
||||||
{
|
{
|
||||||
public static new readonly ManualLogSource Log = Logger.CreateLogSource("UUPatch");
|
public static new readonly ManualLogSource Log = BepInEx.Logging.Logger.CreateLogSource("UUPatch");
|
||||||
|
|
||||||
public static Harmony _hi = new("dev.proxnet.recroom.universalpatch.noneac.il2cpp");
|
public static Harmony _hi = new("dev.proxnet.recroom.universalpatch.noneac.il2cpp");
|
||||||
|
|
||||||
@@ -23,6 +23,10 @@ public class Plugin : BasePlugin
|
|||||||
{
|
{
|
||||||
GenericConfig.LogAllRequests = Config.Bind("Generic", "LogAllRequests", GenericConfigDefaults.LogAllRequests,
|
GenericConfig.LogAllRequests = Config.Bind("Generic", "LogAllRequests", GenericConfigDefaults.LogAllRequests,
|
||||||
"Log all HTTP requests sent by the game.");
|
"Log all HTTP requests sent by the game.");
|
||||||
|
GenericConfig.CertificatePatch = Config.Bind("Generic", "CertificatePatch", GenericConfigDefaults.CertificatePatch,
|
||||||
|
"The game expects a certain SSL certificate from rec.net when making HTTPS requests. Enable this to allow any valid certificate.");
|
||||||
|
GenericConfig.HilePatch = Config.Bind("Generic", "HilePatch", GenericConfigDefaults.HilePatch,
|
||||||
|
"The game will send v1/hile and login+shutdown if winhttp.dll is found. Enable this to add winhttp.dll to the list of allowed DLLs.");
|
||||||
PhotonConfig.PatchPhotonIds = Config.Bind("Photon", "PatchPhotonIds", PhotonConfigDefaults.PatchPhotonIds,
|
PhotonConfig.PatchPhotonIds = Config.Bind("Photon", "PatchPhotonIds", PhotonConfigDefaults.PatchPhotonIds,
|
||||||
"Enable/disable changing the target IDs in PhotonServerSettings." +
|
"Enable/disable changing the target IDs in PhotonServerSettings." +
|
||||||
"\nCustom server settings are not yet supported.");
|
"\nCustom server settings are not yet supported.");
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -1 +1,9 @@
|
|||||||
# undead-universal-patch-il2cpp
|
# Undead Universal Patch
|
||||||
|
Non-EAC, IL2CPP build patcher for Rec Room (Dec 2018\*-*Apr 2020)
|
||||||
|
|
||||||
|
Part two of two universal patches. The Mono patch is available at https://git.proxnet.dev/zombieb/undead-universal-patch-mono.
|
||||||
|
|
||||||
|
### BepInEx Development Build
|
||||||
|
This patch requires that a certain build of BepInEx be used from their GitHub, available at https://github.com/BepInEx/BepInEx/actions/runs/9522461593.
|
||||||
|
|
||||||
|
**When submitting issues**, please submit your BepInEx log file with all log levels enabled. You can do this by setting `Logging.Disk.LogLevels` in `BepInEx.cfg` to `All`.
|
||||||
@@ -27,11 +27,14 @@
|
|||||||
<Reference Include="Il2Cppmscorlib">
|
<Reference Include="Il2Cppmscorlib">
|
||||||
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\BepInEx\interop\Il2Cppmscorlib.dll</HintPath>
|
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\BepInEx\interop\Il2Cppmscorlib.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UnityEngine">
|
<Reference Include="Il2CppSystem">
|
||||||
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\cpp2il_out\UnityEngine.dll</HintPath>
|
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\BepInEx\interop\Il2CppSystem.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Photon3Unity3D">
|
||||||
|
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\cpp2il_out\Photon3Unity3D.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\cpp2il_out\UnityEngine.CoreModule.dll</HintPath>
|
<HintPath>G:\rr\2019-10-25 (5120486837419374208)\BepInEx\interop\UnityEngine.CoreModule.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user