From 5f88c4b7cb7584eae90ce4d41a8735e68575abf1 Mon Sep 17 00:00:00 2001 From: Esska Date: Sat, 11 May 2024 15:22:21 +0200 Subject: [PATCH] Fixed an issue for obfuscation of VRC animator play audio state behavior Added AvatarVersion parameter to exclusion list Layers, state machines, states, blend trees will be obfuscated by default Code refactoring --- Editor/AV3ObfuscatorEditor.cs | 8 +- Editor/Obfuscator.cs | 263 ++++++++++++---------------- Runtime/ObfuscationConfiguration.cs | 1 - package.json | 2 +- 4 files changed, 114 insertions(+), 160 deletions(-) diff --git a/Editor/AV3ObfuscatorEditor.cs b/Editor/AV3ObfuscatorEditor.cs index 0ea2e27..f8262bd 100644 --- a/Editor/AV3ObfuscatorEditor.cs +++ b/Editor/AV3ObfuscatorEditor.cs @@ -101,7 +101,7 @@ public override void OnInspectorGUI() { GUILayout.BeginVertical(GUI.skin.box); { EditorGUILayout.LabelField("- Transforms (entire hierarchy)"); - EditorGUILayout.LabelField("- Controllers"); + EditorGUILayout.LabelField("- Controllers, Layers, State Machines, States, Blend Trees"); EditorGUILayout.LabelField("- Avatar"); EditorGUILayout.LabelField("- Avatar Masks"); EditorGUILayout.LabelField("- Animation Clips"); @@ -123,12 +123,6 @@ public override void OnInspectorGUI() { if (obfus.config.showOptionalObfuscation) { - GUILayout.BeginVertical(GUI.skin.box); - { - obfus.config.obfuscateLayers = EditorGUILayout.ToggleLeft(new GUIContent("Layers, State Machines, States, Blend Trees", "Layers, State Machines, States, Blend Trees of any used Controller"), obfus.config.obfuscateLayers); - } - GUILayout.EndVertical(); - GUILayout.BeginVertical(GUI.skin.box); { obfus.config.obfuscateExpressionParameters = EditorGUILayout.ToggleLeft(new GUIContent("VRC Expression Parameters + Menus", "VRC Expression Parameters, Menu and Submenus"), obfus.config.obfuscateExpressionParameters); diff --git a/Editor/Obfuscator.cs b/Editor/Obfuscator.cs index 7e16540..44fbb45 100644 --- a/Editor/Obfuscator.cs +++ b/Editor/Obfuscator.cs @@ -15,6 +15,7 @@ public class Obfuscator : ScriptableObject { public static readonly List VRC_RESERVED_ANIMATOR_PARAMETERS = new List() { "AFK", "AngularY", + "AvatarVersion", "Earmuffs", "EyeHeightAsMeters", "EyeHeightAsPercent", @@ -558,86 +559,90 @@ AnimatorController ObfuscateController(AnimatorController controller) { List parameters = new List(obfuscatedController.parameters); foreach (var parameter in parameters) { + parameter.name = ObfuscateParameter(parameter.name); + } - if (!allParameters.Contains(parameter.name)) - allParameters.Add(parameter.name); + obfuscatedController.parameters = parameters.ToArray(); - if (config.obfuscateExpressionParameters && config.obfuscateParameters) { + // Layers, avatar masks, state machines, states, blend trees, animation clips + List layers = new List(obfuscatedController.layers); - if (VRC_RESERVED_ANIMATOR_PARAMETERS.Contains(parameter.name)) - continue; + foreach (var layer in layers) { + layer.name = GUID.Generate().ToString(); - if (!config.obfuscatedParameters.Contains(parameter.name)) - continue; + if (layer.avatarMask != null) + layer.avatarMask = ObfuscateAvatarMask(layer.avatarMask); - if (obfuscatedParameters.ContainsKey(parameter.name)) { - parameter.name = obfuscatedParameters[parameter.name]; - } - else { - string newName = GUID.Generate().ToString(); + ObfuscateStateMachine(layer.stateMachine); + } - // Use same GUID for same PhysBones parameter and do not obfuscate suffix + obfuscatedController.layers = layers.ToArray(); - // Parameter in PhysBones component - // Nose -> {GUID} + return obfuscatedController; + } - // Parameter in controller - // Nose_IsGrabbed -> {GUID}_IsGrabbed - // Nose_Angle -> {GUID}_Angle - // Nose_Stretch -> {GUID}_Stretch + throw new System.Exception($"Obfuscation of Controller '{controller.name}' failed"); + } - string physBonesParameterSuffix = GetPhysBonesParameterSuffix(parameter.name); + string ObfuscateParameter(string parameter) { - if (!string.IsNullOrEmpty(physBonesParameterSuffix)) { - string physBonesParameter = GetPhysBonesParameter(parameter.name); - bool foundSamePhysBonesParameter = false; + if (string.IsNullOrEmpty(parameter)) + return parameter; - foreach (var suffix in VRC_PHYS_BONES_SUFFIXES) { + if (!allParameters.Contains(parameter)) + allParameters.Add(parameter); - if (suffix == physBonesParameterSuffix) - continue; + if (!config.obfuscateExpressionParameters || !config.obfuscateParameters) + return parameter; - string samePhysBonesParameterName = physBonesParameter + suffix; + if (VRC_RESERVED_ANIMATOR_PARAMETERS.Contains(parameter)) + return parameter; - if (obfuscatedParameters.ContainsKey(samePhysBonesParameterName)) { - newName = GetPhysBonesParameter(obfuscatedParameters[samePhysBonesParameterName]) + physBonesParameterSuffix; - foundSamePhysBonesParameter = true; - break; - } - } + if (!config.obfuscatedParameters.Contains(parameter)) + return parameter; - if (!foundSamePhysBonesParameter) - newName += physBonesParameterSuffix; - } + if (obfuscatedParameters.ContainsKey(parameter)) + return obfuscatedParameters[parameter]; - obfuscatedParameters.Add(parameter.name, newName); - parameter.name = newName; - } - } - } + string obfuscatedParameter = GUID.Generate().ToString(); - obfuscatedController.parameters = parameters.ToArray(); + // Use same GUID for same PhysBones parameter and do not obfuscate suffix - // Layers, avatar masks, state machines, states, blend trees, animation clips - List layers = new List(obfuscatedController.layers); + // Parameter in PhysBones component + // Nose -> {GUID} - foreach (var layer in layers) { + // Parameter in controller + // Nose_IsGrabbed -> {GUID}_IsGrabbed + // Nose_Angle -> {GUID}_Angle + // Nose_Stretch -> {GUID}_Stretch - if (config.obfuscateLayers) - layer.name = GUID.Generate().ToString(); + string physBonesParameterSuffix = GetPhysBonesParameterSuffix(parameter); - if (layer.avatarMask != null) - layer.avatarMask = ObfuscateAvatarMask(layer.avatarMask); + if (!string.IsNullOrEmpty(physBonesParameterSuffix)) { + string physBonesParameter = GetPhysBonesParameter(parameter); + bool foundSamePhysBonesParameter = false; - ObfuscateStateMachine(layer.stateMachine); - } + foreach (var suffix in VRC_PHYS_BONES_SUFFIXES) { - obfuscatedController.layers = layers.ToArray(); + if (suffix == physBonesParameterSuffix) + continue; - return obfuscatedController; + string samePhysBonesParameterName = physBonesParameter + suffix; + + if (obfuscatedParameters.ContainsKey(samePhysBonesParameterName)) { + obfuscatedParameter = GetPhysBonesParameter(obfuscatedParameters[samePhysBonesParameterName]) + physBonesParameterSuffix; + foundSamePhysBonesParameter = true; + break; + } + } + + if (!foundSamePhysBonesParameter) + obfuscatedParameter += physBonesParameterSuffix; } - throw new System.Exception($"Obfuscation of Controller '{controller.name}' failed"); + obfuscatedParameters.Add(parameter, obfuscatedParameter); + + return obfuscatedParameter; } AvatarMask ObfuscateAvatarMask(AvatarMask avatarMask) { @@ -670,23 +675,18 @@ AvatarMask ObfuscateAvatarMask(AvatarMask avatarMask) { } void ObfuscateStateMachine(AnimatorStateMachine stateMachine) { + stateMachine.name = GUID.Generate().ToString(); - if (config.obfuscateLayers) - stateMachine.name = GUID.Generate().ToString(); - - if (config.obfuscateExpressionParameters && config.obfuscateParameters) { - - foreach (var transition in stateMachine.entryTransitions) { - UpdateTransitionConditionParameters(transition); - } + foreach (var transition in stateMachine.entryTransitions) { + ObfuscateTransitionConditionParameters(transition); + } - foreach (var transition in stateMachine.anyStateTransitions) { - UpdateTransitionConditionParameters(transition); - } + foreach (var transition in stateMachine.anyStateTransitions) { + ObfuscateTransitionConditionParameters(transition); + } - foreach (var behaviour in stateMachine.behaviours) { - ObfuscateBehaviour(behaviour); - } + foreach (var behaviour in stateMachine.behaviours) { + ObfuscateBehaviour(behaviour); } foreach (var state in stateMachine.states) { @@ -699,31 +699,19 @@ void ObfuscateStateMachine(AnimatorStateMachine stateMachine) { } void ObfuscateState(AnimatorState state) { + state.name = GUID.Generate().ToString(); - if (config.obfuscateLayers) - state.name = GUID.Generate().ToString(); - - if (config.obfuscateExpressionParameters && config.obfuscateParameters) { + state.cycleOffsetParameter = ObfuscateParameter(state.cycleOffsetParameter); + state.mirrorParameter = ObfuscateParameter(state.mirrorParameter); + state.speedParameter = ObfuscateParameter(state.speedParameter); + state.timeParameter = ObfuscateParameter(state.timeParameter); - if (obfuscatedParameters.ContainsKey(state.cycleOffsetParameter)) - state.cycleOffsetParameter = obfuscatedParameters[state.cycleOffsetParameter]; - - if (obfuscatedParameters.ContainsKey(state.mirrorParameter)) - state.mirrorParameter = obfuscatedParameters[state.mirrorParameter]; - - if (obfuscatedParameters.ContainsKey(state.speedParameter)) - state.speedParameter = obfuscatedParameters[state.speedParameter]; - - if (obfuscatedParameters.ContainsKey(state.timeParameter)) - state.timeParameter = obfuscatedParameters[state.timeParameter]; - - foreach (var transition in state.transitions) { - UpdateTransitionConditionParameters(transition); - } + foreach (var transition in state.transitions) { + ObfuscateTransitionConditionParameters(transition); + } - foreach (var behaviour in state.behaviours) { - ObfuscateBehaviour(behaviour); - } + foreach (var behaviour in state.behaviours) { + ObfuscateBehaviour(behaviour); } if (state.motion is AnimationClip) @@ -738,22 +726,23 @@ void ObfuscateBehaviour(StateMachineBehaviour behaviour) { VRCAvatarParameterDriver parameterDriver = (VRCAvatarParameterDriver)behaviour; foreach (var parameter in parameterDriver.parameters) { - - if (parameter.name != null && obfuscatedParameters.ContainsKey(parameter.name)) - parameter.name = obfuscatedParameters[parameter.name]; - - if (parameter.source != null && obfuscatedParameters.ContainsKey(parameter.source)) - parameter.source = obfuscatedParameters[parameter.source]; + parameter.name = ObfuscateParameter(parameter.name); + parameter.source = ObfuscateParameter(parameter.source); } } else if (behaviour is VRCAnimatorPlayAudio) { VRCAnimatorPlayAudio animatorPlayAudio = (VRCAnimatorPlayAudio)behaviour; - if (animatorPlayAudio.ParameterName != null && obfuscatedParameters.ContainsKey(animatorPlayAudio.ParameterName)) - animatorPlayAudio.ParameterName = obfuscatedParameters[animatorPlayAudio.ParameterName]; + if (!string.IsNullOrEmpty(animatorPlayAudio.SourcePath)) + animatorPlayAudio.SourcePath = ObfuscateTransformPath(animatorPlayAudio.SourcePath); + + animatorPlayAudio.ParameterName = ObfuscateParameter(animatorPlayAudio.ParameterName); - for (int i = 0; i < animatorPlayAudio.Clips.Length; i++) { - animatorPlayAudio.Clips[i] = ObfuscateAudioClip(animatorPlayAudio.Clips[i]); + if (config.obfuscateAudioClips) { + + for (int i = 0; i < animatorPlayAudio.Clips.Length; i++) { + animatorPlayAudio.Clips[i] = ObfuscateAudioClip(animatorPlayAudio.Clips[i]); + } } } } @@ -846,7 +835,9 @@ BlendTree ObfuscateBlendTree(BlendTree blendTree) { return obfuscatedBlendTrees[blendTree]; } else { - string newPath = GetObfuscatedPath(); + string obfuscatedBlendTreeGUID = GUID.Generate().ToString(); + + string newPath = GetObfuscatedPath(obfuscatedBlendTreeGUID); BlendTree obfuscatedBlendTree = blendTree; if (AssetDatabase.IsMainAsset(blendTree)) { @@ -860,17 +851,10 @@ BlendTree ObfuscateBlendTree(BlendTree blendTree) { } } - if (config.obfuscateLayers) - obfuscatedBlendTree.name = GUID.Generate().ToString(); - - if (config.obfuscateExpressionParameters && config.obfuscateParameters) { - - if (obfuscatedParameters.ContainsKey(obfuscatedBlendTree.blendParameter)) - blendTree.blendParameter = obfuscatedParameters[blendTree.blendParameter]; + obfuscatedBlendTree.name = obfuscatedBlendTreeGUID; - if (obfuscatedParameters.ContainsKey(obfuscatedBlendTree.blendParameterY)) - obfuscatedBlendTree.blendParameterY = obfuscatedParameters[blendTree.blendParameterY]; - } + obfuscatedBlendTree.blendParameter = ObfuscateParameter(obfuscatedBlendTree.blendParameter); + obfuscatedBlendTree.blendParameterY = ObfuscateParameter(obfuscatedBlendTree.blendParameterY); List childMotions = new List(obfuscatedBlendTree.children); @@ -879,19 +863,13 @@ BlendTree ObfuscateBlendTree(BlendTree blendTree) { if (childMotions[i].motion is AnimationClip) { ChildMotion childMotion = childMotions[i]; childMotion.motion = ObfuscateAnimationClip((AnimationClip)childMotion.motion); - - if (obfuscatedParameters.ContainsKey(childMotion.directBlendParameter)) - childMotion.directBlendParameter = obfuscatedParameters[childMotion.directBlendParameter]; - + childMotion.directBlendParameter = ObfuscateParameter(childMotion.directBlendParameter); childMotions[i] = childMotion; } else if (obfuscatedBlendTree.children[i].motion is BlendTree) { ChildMotion childMotion = childMotions[i]; childMotion.motion = ObfuscateBlendTree((BlendTree)obfuscatedBlendTree.children[i].motion); - - if (obfuscatedParameters.ContainsKey(childMotion.directBlendParameter)) - childMotion.directBlendParameter = obfuscatedParameters[childMotion.directBlendParameter]; - + childMotion.directBlendParameter = ObfuscateParameter(childMotion.directBlendParameter); childMotions[i] = childMotion; } } @@ -904,17 +882,13 @@ BlendTree ObfuscateBlendTree(BlendTree blendTree) { throw new System.Exception($"Obfuscation of BlendTree '{blendTree.name}' failed"); } - void UpdateTransitionConditionParameters(AnimatorTransitionBase transition) { + void ObfuscateTransitionConditionParameters(AnimatorTransitionBase transition) { List conditions = new List(transition.conditions); for (int i = 0; i < conditions.Count; i++) { - - if (obfuscatedParameters.ContainsKey(conditions[i].parameter)) { - AnimatorCondition condition = conditions[i]; - condition.parameter = obfuscatedParameters[conditions[i].parameter]; - - conditions[i] = condition; - } + AnimatorCondition condition = conditions[i]; + condition.parameter = ObfuscateParameter(condition.parameter); + conditions[i] = condition; } transition.conditions = conditions.ToArray(); @@ -938,11 +912,7 @@ void ObfuscateExpressionsAndMenus(VRCAvatarDescriptor descriptor) { if (!allParameters.Contains(expressionParameter.name)) Debug.LogError($"VRC Expression Parameter '{expressionParameter.name}' is not used in any controller. It's recommended to remove it.", descriptor.expressionParameters); - if (config.obfuscateParameters) { - - if (obfuscatedParameters.ContainsKey(expressionParameter.name)) - expressionParameter.name = obfuscatedParameters[expressionParameter.name]; - } + expressionParameter.name = ObfuscateParameter(expressionParameter.name); } } } @@ -963,23 +933,15 @@ VRCExpressionsMenu ObfuscateExpressionMenu(VRCExpressionsMenu menu) { obfuscatedExpressionMenus.Add(menu, obfuscatedMenu); foreach (var control in obfuscatedMenu.controls) { + control.parameter.name = ObfuscateParameter(control.parameter.name); - if (config.obfuscateParameters) { - - if (control.parameter != null && obfuscatedParameters.ContainsKey(control.parameter.name)) - control.parameter.name = obfuscatedParameters[control.parameter.name]; - - foreach (var subParameter in control.subParameters) { - - if (subParameter != null && obfuscatedParameters.ContainsKey(subParameter.name)) - subParameter.name = obfuscatedParameters[subParameter.name]; - } + foreach (var subParameter in control.subParameters) { + subParameter.name = ObfuscateParameter(subParameter.name); } if (config.obfuscateMaterials && config.obfuscateTextures && control.icon != null) control.icon = (Texture2D)ObfuscateTexture(control.icon); - if (control.subMenu != null) { if (control.type == VRCExpressionsMenu.Control.ControlType.SubMenu) @@ -1015,12 +977,7 @@ void ObfuscatePhysBonesAndContactReceivers(VRCAvatarDescriptor descriptor) { } foreach (var contactReceiver in contactReceivers) { - - if (!string.IsNullOrEmpty(contactReceiver.parameter)) { - - if (obfuscatedParameters.ContainsKey(contactReceiver.parameter)) - contactReceiver.parameter = obfuscatedParameters[contactReceiver.parameter]; - } + contactReceiver.parameter = ObfuscateParameter(contactReceiver.parameter); } } @@ -1121,8 +1078,12 @@ bool IsObfuscatedGameObject(GameObject gameObject) { return (gameObject.name.Length == (32 + SUFFIX.Length) && gameObject.name.EndsWith(SUFFIX)); } - string GetObfuscatedPath() { - string path = folder + "/" + GUID.Generate(); + string GetObfuscatedPath(string guid = "") { + + if (guid == "") + guid = GUID.Generate().ToString(); + + string path = $"{folder}/{guid}"; if (typeof(T) == typeof(AnimatorController)) path += ".controller"; diff --git a/Runtime/ObfuscationConfiguration.cs b/Runtime/ObfuscationConfiguration.cs index c29291f..dc837d2 100644 --- a/Runtime/ObfuscationConfiguration.cs +++ b/Runtime/ObfuscationConfiguration.cs @@ -6,7 +6,6 @@ namespace Esska.AV3Obfuscator { [Serializable] public class ObfuscationConfiguration { - public bool obfuscateLayers = true; public bool obfuscateExpressionParameters = true; public bool obfuscateParameters = true; public List obfuscatedParameters = new List(); diff --git a/package.json b/package.json index a19e08f..d713a63 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.esska.av3obfuscator", "displayName": "Esska AV3 Obfuscator", - "version": "2.1.4", + "version": "2.2.0", "unity": "2019.4", "description": "Esska AV3Obfuscator allows you to obfuscate your VRChat avatar.", "author": {