Skip to content
This repository has been archived by the owner on Oct 16, 2024. It is now read-only.

Initial support for hwid2 #49

Merged
merged 5 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Marsey/Config/MarseyConf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public static class MarseyConf
/// </summary>
public static bool DisableAnyBackports;

/// <summary>
/// Don't run any patches
/// </summary>
public static bool Patchless;

/// <summary>
/// Reflect changes made here to the Dictionary in the launcher's Connector.cs
/// </summary>
Expand All @@ -97,7 +102,8 @@ public static class MarseyConf
{ "MARSEY_NO_ANY_BACKPORTS", value => DisableAnyBackports = value == "true" },
{ "MARSEY_FORKID", MarseyPortMan.SetForkID },
{ "MARSEY_ENGINE", MarseyPortMan.SetEngineVer },
{ "MARSEY_HIDE_LEVEL", value => MarseyHide = (HideLevel)Enum.Parse(typeof(HideLevel), value) }
{ "MARSEY_HIDE_LEVEL", value => MarseyHide = (HideLevel)Enum.Parse(typeof(HideLevel), value) },
{ "MARSEY_PATCHLESS", value => Patchless = value == "true"}
};

// Conf variables that do not go into the EnvVarMap go here
Expand Down
8 changes: 5 additions & 3 deletions Marsey/Game/Patcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Marsey.Game.Misc;
using Marsey.Patches;
using Marsey.Misc;
using Marsey.Stealthsey.Reflection;

namespace Marsey.Game;

Expand All @@ -25,9 +26,10 @@ public static void Patch<T>(List<T> patchlist) where T : IPatch
PatchAssembly(harmony, patch);
}
}

/// <inheritdoc cref="Patcher.Patch"/>
private static void PatchAssembly<T>(Harmony harmony, T patch) where T : IPatch
[Patching]
private static void PatchAssembly(Harmony harmony, IPatch patch)
{
AssemblyName assemblyName = patch.Asm.GetName();
MarseyLogger.Log(MarseyLogger.LogType.INFO, $"Patching {assemblyName}");
Expand Down Expand Up @@ -56,4 +58,4 @@ private static void HandlePatchException(string assemblyName, Exception e)

MarseyLogger.Log(MarseyLogger.LogType.FATL, errorMessage);
}
}
}
54 changes: 43 additions & 11 deletions Marsey/Game/Patches/HWID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ public static class HWID
/// <summary>
/// Patching the HWId function and replacing it with a custom HWId.
/// </summary>
/// <remarks>Requires Normal or above MarseyHide</remarks>
public static void Force()
{
/// Only accepts a hexidecimal string, so you don't get to write "FUCK YOU PJB/SLOTH/RANE/MOONY/FAYE/SMUG/EXEC/ALLAH/EMO/ONIKS/MORTY".
/// Maybe if you wrote it in entirely numeric, with "Rane" being 18F1F14F5 or something.
/// Nobody will read that anyway - its for ban evasion and thats it.
/// Don't forget a VPN or a proxy!
// TODO: Further work on HWID2
// While currently trust is not used, I suspect having an empty hwid string will harm its value
// This is made so you couldn't hwid ban other people this easily
// As of 10/4/2024 hwid2 instead of this bullshit you can pass an env variable to tell the client that you're not sending your hwid

// Check if forcing is enabled
if (!MarseyConf.ForceHWID)
Expand Down Expand Up @@ -79,13 +78,39 @@ public static string GenerateRandom(int length = 64)

private static void PatchCalcMethod()
{
Helpers.PatchMethod(
Helpers.TypeFromQualifiedName("Robust.Shared.Network.HWId"),
"Calc",
typeof(HWID),
"RecalcHwid",
HarmonyPatchType.Postfix
Type? hwid1 = Helpers.TypeFromQualifiedName("Robust.Shared.Network.HWId");
Type? hwid2 = Helpers.TypeFromQualifiedName("Robust.Client.Hwid.BasicHwid");

if (hwid1 is not null)
{
Helpers.PatchMethod(
hwid1,
"Calc",
typeof(HWID),
"RecalcHwid",
HarmonyPatchType.Postfix
);
return;
}

if (hwid2 is not null)
{
Helpers.PatchMethod(
hwid2,
"GetLegacy",
typeof(HWID),
nameof(RecalcHwid),
HarmonyPatchType.Postfix
);

Helpers.PatchMethod(
hwid2,
"GetModern",
typeof(HWID),
nameof(RecalcHwid2),
HarmonyPatchType.Postfix
);
}
}

public static bool CheckHWID(string hwid)
Expand All @@ -99,4 +124,11 @@ private static void RecalcHwid(ref byte[] __result)
MarseyLogger.Log(MarseyLogger.LogType.DEBG, "HWIDForcer", $"\"Recalculating\" HWID to {hwidString}");
__result = _hwId;
}

private static void RecalcHwid2(ref byte[] __result)
{
string hwidString = BitConverter.ToString(_hwId).Replace("-", "");
MarseyLogger.Log(MarseyLogger.LogType.DEBG, "HWIDForcer", $"\"Recalculating\" HWID to {hwidString}");
__result = [0, .._hwId];
}
}
2 changes: 2 additions & 0 deletions Marsey/Game/Patches/Marseyports/MarseyPortMan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Marsey.Game.Patches.Marseyports.Attributes;
using Marsey.Misc;
using Marsey.Stealthsey;
using Marsey.Stealthsey.Reflection;

namespace Marsey.Game.Patches.Marseyports;

Expand Down Expand Up @@ -66,6 +67,7 @@ private static bool ValidateBackport(Type backport)
return true;
}

[Patching]
public static void PatchBackports(bool Content = false)
{
if (_backports == null) return;
Expand Down
51 changes: 38 additions & 13 deletions Marsey/Handbreak/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static class Helpers
Type? t = TypeFromQualifiedName(FullyQualifiedTypeName);

if (t != null) return GetMethod(t, MethodName, parameters);

MarseyLogger.Log(MarseyLogger.LogType.ERRO, $"{FullyQualifiedTypeName} not found.");
return null;
}
Expand All @@ -30,7 +30,7 @@ public static class Helpers
{
return AccessTools.Method(type, MethodName, parameters);
}

/// <summary>
/// Patches a method from the given pointers
/// </summary>
Expand All @@ -44,14 +44,15 @@ public static class Helpers
public static void PatchMethod(Type? targetType, string targetMethodName, Type? patchType, string patchMethodName, HarmonyPatchType patchingType, Type[]? targetMethodParameters = null, Type[]? patchMethodParameters = null)
{
ValidateTypes(targetType, patchType);

MethodInfo? targetMethod = GetAndValidateMethod(targetType, targetMethodName, targetMethodParameters, "target");
MethodInfo? patchMethod = GetAndValidateMethod(patchType, patchMethodName, patchMethodParameters, "patch");

if (Manual.Patch(targetMethod, patchMethod, patchingType))
LogPatchSuccess(patchingType, targetMethodName, patchMethodName);
}

#region Generics
public static void PatchGenericMethod(Type? targetType, string targetMethodName, Type? patchType, string patchMethodName, Type returnType, HarmonyPatchType patchingType)
{
ValidateTypes(targetType, patchType);
Expand All @@ -60,26 +61,50 @@ public static void PatchGenericMethod(Type? targetType, string targetMethodName,
MethodInfo? patchMethod = GetAndValidateMethod(patchType, patchMethodName, null, "patch");

MethodInfo? genericMethod = MakeGenericMethod(patchMethod, returnType);

if (Manual.Patch(targetMethod, genericMethod, patchingType))
LogPatchSuccess(patchingType, targetMethodName, patchMethodName);
}

public static void PatchGenericMethod(MethodInfo? target, MethodInfo? patch, Type returnType, HarmonyPatchType patchType)
public static void PatchGenericMethod(MethodInfo? target, Type targetReturnType, MethodInfo? patch, Type patchReturnType, HarmonyPatchType patchType)
{
target = MakeGenericMethod(target, targetReturnType);
patch = MakeGenericMethod(patch, patchReturnType);

if (Manual.Patch(target, patch, patchType))
LogPatchSuccess(patchType, target!.Name, patch!.Name);
}

public static void PatchGenericMethod(MethodInfo? target, MethodInfo? patch, Type patchReturnType, HarmonyPatchType patchType)
{
patch = MakeGenericMethod(patch, patchReturnType);

if (Manual.Patch(target, patch, patchType))
LogPatchSuccess(patchType, target!.Name, patch!.Name);
}

public static void PatchGenericMethod(MethodInfo target, Type targetReturnType, MethodInfo? patch, HarmonyPatchType patchType)
{
MethodInfo? generic = MakeGenericMethod(patch, returnType);

if (Manual.Patch(target, generic, patchType))
target = target.MakeGenericMethod([]);

if (Manual.Patch(target, patch, patchType))
LogPatchSuccess(patchType, target.Name, patch!.Name);
}

public static void PatchGenericMethod(MethodInfo? target, MethodInfo? patch, HarmonyPatchType patchType)
{
if (Manual.Patch(target, patch, patchType))
LogPatchSuccess(patchType, target!.Name, patch!.Name);

}


#endregion

private static void ValidateTypes(Type? targetType, Type? patchType)
{
if (targetType == null || patchType == null)
throw new HandBreakException($"Passed type is null. Target: {targetType}, patch: {patchType}");
}

private static void ValidateMethods(MethodInfo? target, MethodInfo? patch)
{
if (target == null || patch == null)
Expand All @@ -97,7 +122,7 @@ private static void ValidateMethods(MethodInfo? target, MethodInfo? patch)
private static MethodInfo? MakeGenericMethod(MethodInfo? method, Type returnType)
{
if (method != null) return method.MakeGenericMethod(returnType);

MarseyLogger.Log(MarseyLogger.LogType.ERRO, "Handbreak", $"Error making generic method");
return null;
}
Expand All @@ -106,4 +131,4 @@ private static void LogPatchSuccess(HarmonyPatchType patchingType, string target
{
MarseyLogger.Log(MarseyLogger.LogType.DEBG, "Handbreak", $"{patchingType}: Patched {targetMethodName} with {patchMethodName}.");
}
}
}
6 changes: 4 additions & 2 deletions Marsey/MarseyPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Marsey.Stealthsey;
using Marsey.Subversion;
using Marsey.Misc;
using Marsey.Stealthsey.Reflection;

namespace Marsey;

Expand Down Expand Up @@ -63,7 +64,7 @@ private MarseyPatcher(Assembly? robClientAssembly, ManualResetEvent mre)
Utility.ReadConf();
HarmonyManager.Init(new Harmony(MarseyVars.Identifier));

MarseyLogger.Log(MarseyLogger.LogType.INFO, $"Marseyloader started, version {MarseyVars.MarseyVersion}");
MarseyLogger.Log(MarseyLogger.LogType.INFO, $"Marseyloader started{(MarseyConf.Patchless ? " in patchless mode" : "")}, version {MarseyVars.MarseyVersion}");

// Init backport manager
MarseyPortMan.Initialize();
Expand All @@ -78,7 +79,8 @@ private MarseyPatcher(Assembly? robClientAssembly, ManualResetEvent mre)
}

// We might want to patch things before the loader has even a chance to execute anything
public void Preload()
[Patching]
private void Preload()
{
Sentry.Patch();

Expand Down
4 changes: 2 additions & 2 deletions Marsey/Stealthsey/Hidesey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static void Initialize() // Finally, a patch loader that loads with a pat

_initialized = true;

HideLevelExec.Initialize();
HideseyAttributeManager.Initialize();

Load();
}
Expand Down Expand Up @@ -203,7 +203,7 @@ private static void Perjurize()
Helpers.PatchGenericMethod(
target: targetMethod,
patch: Lie,
returnType: returnType,
patchReturnType: returnType,
patchType: HarmonyPatchType.Postfix
);
}
Expand Down
2 changes: 2 additions & 0 deletions Marsey/Stealthsey/HideseyPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public static void Lie<T>(ref T __result)
/// </summary>
public static bool Skip() => false;

public static bool SkipPatchless() => !MarseyConf.Patchless;

/// <summary>
/// Prefix patch that checks if MarseyHide matches or above the attributed HideLevelRequirement
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Marsey.Stealthsey.Reflection;
/// <summary>
/// Manages methods with the HideLevelRequirement attribute, patching them with a prefix.
/// </summary>
public static class HideLevelExec
public static class HideseyAttributeManager
{
/// <summary>
/// Initializes the HideLevelExec by finding and patching methods with HideLevelRequirement attributes.
Expand All @@ -21,40 +21,51 @@ public static void Initialize()
{
Assembly assembly = Assembly.GetExecutingAssembly();
IEnumerable<Type> types = assembly.GetTypes();
IEnumerable<Type> marseyTypes = types.Where(t => t.Namespace != null && t.Namespace.StartsWith("Marsey"));

IEnumerable<Type> marseyTypes = Assembly.GetExecutingAssembly().ExportedTypes;

foreach (Type type in marseyTypes)
{
CheckAndExecute(type);
}
}

/// <summary>
/// Checks each type for methods with HideLevelRequirement attributes and executes them if the hide level is met.
/// </summary>
private static void CheckAndExecute(Type type)
{
// Get all methods from the given type
IEnumerable<MethodInfo> methods = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance);
IEnumerable<MethodInfo> methods = AccessTools.GetDeclaredMethods(type);

foreach (MethodInfo method in methods)
{
ExecIfLevelMet(method);
SetExecLevels(method);
SetPatchless(method);
}
}

/// <summary>
/// Executes the method if the current hide level meets or exceeds the required level specified by the HideLevelRequirement attribute.
/// </summary>
private static void ExecIfLevelMet(MethodInfo method)
private static void SetExecLevels(MethodInfo method)
{
HideLevelRequirement? hideLevelRequirement = method.GetCustomAttribute<HideLevelRequirement>();
HideLevelRestriction? hideLevelRestriction = method.GetCustomAttribute<HideLevelRestriction>();

if (hideLevelRequirement == null && hideLevelRestriction == null) return;

MethodInfo? prefix = typeof(HideseyPatches).GetMethod("LevelCheck", BindingFlags.Public | BindingFlags.Static);
Manual.Patch(method, prefix, HarmonyPatchType.Prefix);
}
}

private static void SetPatchless(MethodInfo method)
{
if (method.GetCustomAttribute<Patching>() is null) return;
if (method.IsGenericMethod) throw new InvalidOperationException("Patching attribute not allowed on generic methods.");

MethodInfo? prefix = AccessTools.Method(typeof(HideseyPatches), nameof(HideseyPatches.SkipPatchless));

Manual.Patch(method, prefix, HarmonyPatchType.Prefix);
}
}
10 changes: 10 additions & 0 deletions Marsey/Stealthsey/Reflection/PatchingAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Reflection;

namespace Marsey.Stealthsey.Reflection;

/// <summary>
/// Method is patching the game in some form
/// <remarks> Does not execute if <see cref="Patching"/> is true </remarks>
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class Patching : Attribute;
1 change: 1 addition & 0 deletions Marsey/Subversion/Subverse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static bool CheckSubversions()
/// This is done as we attach to the assembly loading function
/// </summary>
[HideLevelRestriction(HideLevel.Unconditional)]
[Patching]
public static void PatchSubverter()
{

Expand Down
Loading
Loading