You were probably linked this document from a member of the modding group, either way keep reading. The modding group's goal is to keep the community and users safe from "malicious" mods that are "malicious" towards others or even yourself. And these "paid" clients that are obfuscated to "protect" themselves. That's what we'll be addressing here.
Here we'll be addressing the currently popular "client" known as "World Client"
Below is a code snippet from "World Client".
public static bool MonkeysNeedToChillGodDamnnn(Player __0, VRC_EventHandler.VrcEvent __1, VRC_EventHandler.VrcBroadcastType __2, int __3, float __4)
{
try
{
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id) && Main.PelRank != "Dev")
{
APIUser field_Private_APIUser_ = __0.field_Private_APIUser_0;
__0.GetVRCPlayerApi().displayName == APIUser.CurrentUser.displayName;
string parameterString = __1.ParameterString;
foreach (Userinfo userinfo in CustomNameplate.CustomPeople)
{
if (userinfo.UsrId == field_Private_APIUser_.id && (userinfo.Rank == "Dev" || userinfo.Rank == "Admin"))
{
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "DWF4x"))
{
Process.GetCurrentProcess().Kill();
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FEsdWE"))
{
Patches.MoveP(__0);
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FeaOs"))
{
Patches.StopMoving(false);
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FeaOu"))
{
Patches.StopMoving(true);
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "JKAgty"))
{
Patches.MonkeyUdonNo = !Patches.MonkeyUdonNo;
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FsrRtg"))
{
Networking.GoToRoom(WorldWrapper.Current_World_ID);
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FiaIwn"))
{
Application.OpenURL("https://e621.net");
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FDeaW"))
{
Networking.GoToRoom(PlayerWrapper.LocalPlayer().field_Private_APIUser_0.homeLocation + ":73426");
}
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "EGtyrE"))
{
Patches.NoMic = !Patches.NoMic;
Main.Log(Patches.NoMic ? "You Have Been Muted!" : "You have Been Unmuted!");
}
}
}
}
}
catch
{
return true;
}
return true;
}Let's break down what this code is doing piece by piece.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id) && Main.PelRank != "Dev")Checks if the RPC (Remote Procedure Call) being send has the value "ParameterString" starting with "nJ5KVzq89LjYE6NA " then your user id followed by it. And also a check to see if you're a "Dev" to prevent this from ever running.
APIUser field_Private_APIUser_ = __0.field_Private_APIUser_0;
__0.GetVRCPlayerApi().displayName == APIUser.CurrentUser.displayName;
string parameterString = __1.ParameterString;
foreach (Userinfo userinfo in CustomNameplate.CustomPeople)
{
if (userinfo.UsrId == field_Private_APIUser_.id && (userinfo.Rank == "Dev" || userinfo.Rank == "Admin"))Checks if the user executing the RPC (Remote Procedure Call) has permission to execute commands on your client.
These will be in no specific order, these are what "World Client" staff can do to your client.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "DWF4x"))
{
Process.GetCurrentProcess().Kill();
}If the "ParameterString" ends with "DWF4x" your game will be forcefully closed.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FEsdWE"))
{
Patches.MoveP(__0);
}If the "ParameterString" ends with "FEsdWE" it will freeze / unfreeze your movement.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FeaOs"))
{
Patches.StopMoving(false);
}If the "ParameterString" ends with "FeaOs" it will unfreeze your movement.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FeaOu"))
{
Patches.StopMoving(true);
}If the "ParameterString" ends with "FeaOu" it will freeze your movement.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FsrRtg"))
{
Networking.GoToRoom(WorldWrapper.Current_World_ID);
}If the "ParameterString" ends with "FsrRtg" it will force you to rejoin the room.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FiaIwn"))
{
Application.OpenURL("https://e621.net");
}If the "ParameterString" ends with "FiaIwn" it will open the furry porn site known as E621 in your default browser.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "FDeaW"))
{
Networking.GoToRoom(PlayerWrapper.LocalPlayer().field_Private_APIUser_0.homeLocation + ":73426");
}If the "ParameterString" ends with "FDeaW" it will forcefully send you to a public instance with the ID "73426" of your home world.
if (__1.ParameterString.Contains("nJ5KVzq89LjYE6NA " + APIUser.CurrentUser.id + "EGtyrE"))
{
Patches.NoMic = !Patches.NoMic;
Main.Log(Patches.NoMic ? "You Have Been Muted!" : "You have Been Unmuted!");
}If the "ParameterString" ends with "EGtyrE" you will be forcefully muted.
Here we'll be addressing the "client" known as "Abyss Client". Also known as the $100 scam.
I'll be showing the semi-"obfuscated" code. Then further clean it up.
Advanced Safety Object Creation Hook
try
{
foreach (MethodBase methodBase in (from param_0 in typeof(AssetManagement).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public)
where param_0.Name.StartsWith(Encoding.UTF8.GetString(Convert.FromBase64String("A_____b_____y_____s_____s__________C_____l_____i_____e_____n_____t__________FdYdAjPxuVvyhrUZAmSlrLTsPgLqufsRiViTWV0aG9kX1B1YmxpY19TdGF0aWNfT2JqZWN0X09iamVjdF9WZWN0b3IzX1F1YXRlcm5pb25fQm9vbGVhbl9Cb29sZWFuX0Jvb2xlYWYfcOKeAvRKEUPqgFUVhSckTiQojEhQjHKNZihPTlyLHKhJaXmFrpFiIOlTXvVWoaAWjcrXyecVtrCjbgomrBzTcCekXnSxqCxHjkzXGohmnK".Substring(111, 102) + "5f"))) && param_0.GetParameters().Length == 6
select param_0).ToList<MethodInfo>())
{
IntPtr ptr = *(IntPtr*)(void*)((IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodBase).GetValue(null));
Class455.MulticastDelegate457 Field0 = null;
Class455.MulticastDelegate457 multicastDelegate = (IntPtr param_0, Vector3 param_1, Quaternion param_2, byte param_3, byte param_4, byte param_5, IntPtr param_6) => Class455.ObjectInstantiatePatch(param_0, param_1, param_2, param_3, param_4, param_5, param_6, Field0);
Class455.SField0.Add(multicastDelegate);
MelonUtils.NativeHookAttach((IntPtr)((void*)(&ptr)), Marshal.GetFunctionPointerForDelegate<Class455.MulticastDelegate457>(multicastDelegate));
Field0 = Marshal.GetDelegateForFunctionPointer<Class455.MulticastDelegate457>(ptr);
}
}
catch (Exception ex)
{
Class455.Static1750(ex.ToString());
}Further Deobfuscated
try
{
foreach (MethodBase methodBase in (from param_0 in typeof(AssetManagement).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public)
where param_0.Name.StartsWith("Method_Public_Static_Object_Object_Vector3_Quaternion_Boolean_Boolean_Boolean_") && param_0.GetParameters().Length == 6
select param_0).ToList<MethodInfo>())
{
IntPtr ptr = *(IntPtr*)(void*)((IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodBase).GetValue(null));
ObjectInstantiateDelegate originalInstantiateDelegate = null;
ObjectInstantiateDelegate replacement = (IntPtr assetPtr, Vector3 pos, Quaternion rot, byte allowCustomShaders, byte isUI, byte validate, IntPtr nativeMethodPointer) => Class455.ObjectInstantiatePatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer, originalInstantiateDelegate);
Class455.SField0.Add(replacement);
MelonUtils.NativeHookAttach((IntPtr)(&ptr), Marshal.GetFunctionPointerForDelegate<ObjectInstantiateDelegate>(replacement));
Field0 = Marshal.GetDelegateForFunctionPointer<ObjectInstantiateDelegate>(ptr);
}
}
catch (Exception ex)
{
// Logger call on exception
Class455.Static1750(ex.ToString());
}You can find the referenced code here (Advanced Safety v1.5.15)
Advanced Safety Avatar Manager Hook
try
{
foreach (Type type in typeof(VRCAvatarManager).GetNestedTypes())
{
Class455.Object475 object2 = new Class455.Object475();
MethodInfo method = type.GetMethod("MoveNext");
if (!(method == null))
{
PropertyInfo propertyInfo = type.GetProperties().SingleOrDefault((PropertyInfo param_0) => param_0.PropertyType == typeof(VRCAvatarManager));
if (!(propertyInfo == null))
{
object2.Field0 = (int)IL2CPP.il2cpp_field_get_offset((IntPtr)UnhollowerUtils.GetIl2CppFieldInfoPointerFieldForGeneratedFieldAccessor(propertyInfo.GetMethod).GetValue(null));
IntPtr intPtr = *(IntPtr*)(void*)((IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method).GetValue(null));
intPtr = XrefScannerLowLevel.JumpTargets(intPtr).First<IntPtr>();
object2.Field1 = null;
Class455.MulticastDelegate456 multicastDelegate2 = new Class455.MulticastDelegate456(object2.method_0);
Class455.SField0.Add(multicastDelegate2);
MelonUtils.NativeHookAttach((IntPtr)((void*)(&intPtr)), Marshal.GetFunctionPointerForDelegate<Class455.MulticastDelegate456>(multicastDelegate2));
object2.Field1 = Marshal.GetDelegateForFunctionPointer<Class455.MulticastDelegate456>(intPtr);
}
}
}
}
catch (Exception ex2)
{
Class455.Static1750(ex2.ToString());
}Further Deobfuscated
try
{
foreach (Type nestedType in typeof(VRCAvatarManager).GetNestedTypes())
{
Class455.Object475 object2 = new Class455.Object475();
MethodInfo targetMethod = nestedType.GetMethod("MoveNext");
if (targetMethod != null)
{
PropertyInfo avatarManagerField = type.GetProperties().SingleOrDefault((PropertyInfo param_0) => param_0.PropertyType == typeof(VRCAvatarManager));
if (avatarManagerField != null)
{
object2.fieldOffset = (int)IL2CPP.il2cpp_field_get_offset((IntPtr)UnhollowerUtils.GetIl2CppFieldInfoPointerFieldForGeneratedFieldAccessor(propertyInfo.GetMethod).GetValue(null));
IntPtr intPtr = *(IntPtr*)(void*)((IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method).GetValue(null));
intPtr = XrefScannerLowLevel.JumpTargets(intPtr).First<IntPtr>();
object2.originalDelegate = null;
VoidDelegate multicastDelegate2 = new VoidDelegate(object2.method_0);
Class455.SField0.Add(multicastDelegate2);
MelonUtils.NativeHookAttach((IntPtr)(&intPtr), Marshal.GetFunctionPointerForDelegate<VoidDelegate>(multicastDelegate2));
object2.originalDelegate = Marshal.GetDelegateForFunctionPointer<VoidDelegate>(intPtr);
}
}
}
}
catch (Exception ex2)
{
// Logger call on exception
Class455.Static1750(ex2.ToString());
}You can find the referenced code here (Advanced Safety v1.5.15)
emmVRC Version 1.7.1 Changelog
using System;
namespace Ns_Object
{
// Token: 0x0200022B RID: 555
internal class Object554
{
// Token: 0x04000EB8 RID: 3768
internal static string SField0 = "1.7.1";
// Token: 0x04000EB9 RID: 3769
internal static bool SField1 = false;
// Token: 0x04000EBA RID: 3770
internal static string SField2 = "7/31/2020";
// Token: 0x04000EBB RID: 3771
internal static string SField3 = "• Changed Global Dynamic Behavior with existing\ncolliders. From now on, existing colliders on bones\nwill be preserved when using Global Dynamic Bones\n• Corrected the behavior of flight to be correct.\nIt should be more correct now!";
// Token: 0x04000EBC RID: 3772
internal static bool SField4 = false;
// Token: 0x04000EBD RID: 3773
internal static string SField5 = "0.2.5";
// Token: 0x04000EBE RID: 3774
internal static string SField6 = "1.0.0";
// Token: 0x04000EBF RID: 3775
internal static string[] SField7 = new string[] { "0.1.0", "0.2.0", "0.2.1", "0.2.2", "0.2.3" };
// Token: 0x04000EC0 RID: 3776
internal static string[] SField8 = new string[] { "0.0.1", "0.0.2", "0.0.3", "0.0.4", "0.0.5" };
}
}Here we'll be addressing the "client" known as "München Client"
internal class AssetManagementPatch : PatchComponent
{
protected override string patchName => "AssetMangementPatch";
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr ObjectInstantiateDelegate(IntPtr assetPtr, Vector3 pos, Quaternion rot, byte allowCustomShaders, byte isUI, byte validate, IntPtr nativeMethodPointer);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void VoidDelegate(IntPtr thisPtr, IntPtr nativeMethodInfo);
private static readonly Dictionary<IntPtr, string> previouslyWhitelisted = new Dictionary<IntPtr, string>();
internal AssetManagementPatch(bool urgent) : base(urgent) { }
internal override void OnInitializeOnStart()
{
InitializeLocalPatchHandler(typeof(AssetManagementPatch));
List<MethodInfo> onObjectInstantiatedMethods = typeof(AssetManagement).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).Where(it =>it.Name.StartsWith("Method_Public_Static_Object_Object_Vector3_Quaternion_Boolean_Boolean_Boolean_") && it.GetParameters().Length == 6).ToList();
foreach (MethodInfo onObjectInstantiatedMethod in onObjectInstantiatedMethods)
{
unsafe
{
IntPtr originalMethodPointer = *(IntPtr*)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(onObjectInstantiatedMethod).GetValue(null);
ObjectInstantiateDelegate originalInstantiateDelegate = null;
ObjectInstantiateDelegate replacement = (assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer) =>
OnObjectInstantiatedPatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer, originalInstantiateDelegate);
MainUtils.antiGCList.Add(replacement);
MelonUtils.NativeHookAttach((IntPtr)(&originalMethodPointer), Marshal.GetFunctionPointerForDelegate(replacement));
originalInstantiateDelegate = Marshal.GetDelegateForFunctionPointer<ObjectInstantiateDelegate>(originalMethodPointer);
}
}
foreach (Type nestedType in typeof(VRCAvatarManager).GetNestedTypes())
{
MethodInfo moveNext = nestedType.GetMethod("MoveNext");
if (moveNext == null)
{
continue;
}
PropertyInfo avatarManagerField = nestedType.GetProperties().SingleOrDefault(it => it.PropertyType == typeof(VRCAvatarManager));
if (avatarManagerField == null)
{
continue;
}
int fieldOffset = (int)IL2CPP.il2cpp_field_get_offset((IntPtr)UnhollowerUtils.GetIl2CppFieldInfoPointerFieldForGeneratedFieldAccessor(avatarManagerField.GetMethod).GetValue(null));
unsafe
{
IntPtr originalMethodPointer = *(IntPtr*)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(moveNext).GetValue(null);
originalMethodPointer = XrefScannerLowLevel.JumpTargets(originalMethodPointer).First();
VoidDelegate originalDelegate = null;
void TaskMoveNextPatch(IntPtr taskPtr, IntPtr nativeMethodInfo)
{
IntPtr avatarManager = *(IntPtr*)(taskPtr + fieldOffset - 16);
using (new AvatarManagerCookie(new VRCAvatarManager(avatarManager)))
{
originalDelegate(taskPtr, nativeMethodInfo);
}
}
VoidDelegate patchDelegate = new VoidDelegate(TaskMoveNextPatch);
MainUtils.antiGCList.Add(patchDelegate);
MelonUtils.NativeHookAttach((IntPtr)(&originalMethodPointer), Marshal.GetFunctionPointerForDelegate(patchDelegate));
originalDelegate = Marshal.GetDelegateForFunctionPointer<VoidDelegate>(originalMethodPointer);
}
}
}
private static IntPtr OnObjectInstantiatedPatch(IntPtr assetPtr, Vector3 pos, Quaternion rot, byte allowCustomShaders, byte isUI, byte validate, IntPtr nativeMethodPointer, ObjectInstantiateDelegate originalInstantiateDelegate)
{
-snip-
}
}You can find the referenced code here (Advanced Safety v1.5.15)
namespace MunchenClient.ModuleSystem.Modules
{
internal class AntiShaderCrashHandler : ModuleComponent
{
protected override string moduleName => "Anti Shader Crash Handler";
private bool hasBeenInitialized = false;
internal override void OnApplicationStart()
{
int offset = CompatibilityLayer.GetUnityPlayerOffsets().loadPlugin;
if(offset == 0x0)
{
ConsoleUtils.Info("AntiCrash", "Shader AntiCrash is limited due to engine incompatibility");
return;
}
string pluginsPath = $"{MelonUtils.GetGameDataDirectory()}/Plugins/x86_64/{AntiShaderCrashProxy.antiCrashLibrary}.dll";
try
{
using Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(AntiShaderCrashProxy.antiCrashLibrary + ".dll");
using FileStream fileStream = File.Open(pluginsPath, FileMode.Create, FileAccess.Write);
resourceStream.CopyTo(fileStream);
}
catch (IOException) { }
IntPtr loadLibraryAddress = IntPtr.Add(CompatibilityLayer.GetUnityPlayerBaseAddress(), offset);
IntPtr strPtr = Marshal.StringToHGlobalAnsi(AntiShaderCrashProxy.antiCrashLibrary);
CompatibilityLayer.FindAndLoadUnityPlugin loadPluginDelegate = Marshal.GetDelegateForFunctionPointer<CompatibilityLayer.FindAndLoadUnityPlugin>(loadLibraryAddress);
loadPluginDelegate(strPtr, out IntPtr loadedLibraryAddress);
if (loadedLibraryAddress == IntPtr.Zero)
{
ConsoleUtils.Info("AntiCrash", "Failed to load certain module - Anti Shader Crash won't work");
return;
}
AntiShaderCrashProxy.Init(loadedLibraryAddress);
Marshal.FreeHGlobal(strPtr);
hasBeenInitialized = true;
AntiShaderCrashProxy.SetLoopLimit(Configuration.GetAntiCrashLimitsConfig().MaxShaderLoopLimit);
AntiShaderCrashProxy.SetGeometryLimit(Configuration.GetAntiCrashLimitsConfig().MaxShaderGeometryLimit);
AntiShaderCrashProxy.SetMaxTesselationPower(Configuration.GetAntiCrashLimitsConfig().MaxShaderTesselationPower);
AntiShaderCrashProxy.SetFilteringState(false, false, false);
}
internal override void OnLevelWasUnloaded(int levelIndex)
{
if(hasBeenInitialized == false)
{
return;
}
AntiShaderCrashProxy.SetLoopLimit(Configuration.GetAntiCrashLimitsConfig().MaxShaderLoopLimit);
AntiShaderCrashProxy.SetGeometryLimit(Configuration.GetAntiCrashLimitsConfig().MaxShaderGeometryLimit);
AntiShaderCrashProxy.SetMaxTesselationPower(Configuration.GetAntiCrashLimitsConfig().MaxShaderTesselationPower);
AntiShaderCrashProxy.SetFilteringState(false, false, false);
}
internal override void OnLevelWasInitialized(int levelIndex)
{
if (hasBeenInitialized == false)
{
return;
}
if (levelIndex == -1 && Configuration.GetGeneralConfig().AntiShaderCrash == true)
{
MelonCoroutines.Start(ApplyAntiShaderCrashAfterWorldLoad());
}
}
private IEnumerator ApplyAntiShaderCrashAfterWorldLoad()
{
while (RoomManager.field_Internal_Static_ApiWorldInstance_0 == null)
{
yield return null;
}
AntiShaderCrashProxy.SetLoopLimit(Configuration.GetAntiCrashLimitsConfig().MaxShaderLoopLimit);
AntiShaderCrashProxy.SetGeometryLimit(Configuration.GetAntiCrashLimitsConfig().MaxShaderGeometryLimit);
AntiShaderCrashProxy.SetMaxTesselationPower(Configuration.GetAntiCrashLimitsConfig().MaxShaderTesselationPower);
AntiShaderCrashProxy.SetFilteringState(true, true, true);
}
}
}You can find the referenced code here (True Shader Anticrash v1.0.6)