diff --git a/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs b/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs index 821e78d..f12d368 100644 --- a/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs +++ b/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs @@ -52,7 +52,6 @@ namespace Obfuz.EncryptionVM File.WriteAllText(outputFile, code, Encoding.UTF8); Debug.Log($"Generate EncryptionVM code to {outputFile}"); - UnityEditor.AssetDatabase.Refresh(); } private string GenerateCode() diff --git a/Editor/GarbageCodeGeneration/ConfigGarbageCodeGenerator.cs b/Editor/GarbageCodeGeneration/ConfigGarbageCodeGenerator.cs index 5d0eb57..9351adb 100644 --- a/Editor/GarbageCodeGeneration/ConfigGarbageCodeGenerator.cs +++ b/Editor/GarbageCodeGeneration/ConfigGarbageCodeGenerator.cs @@ -4,135 +4,14 @@ using Obfuz.Settings; using Obfuz.Utils; using System; using System.Collections; -using System.Collections.Generic; -using System.IO; +using System.Linq; using System.Text; -using UnityEngine; namespace Obfuz.GarbageCodeGeneration { - public abstract class SpecificGarbageCodeGeneratorBase : ISpecificGarbageCodeGenerator - { - protected interface IClassGenerationInfo - { - string Namespace { get; set; } - - string Name { get; set; } - - IList Fields { get; set; } - - IList Methods { get; set; } - } - - protected class ClassGenerationInfo : IClassGenerationInfo - { - public string Namespace { get; set; } - public string Name { get; set; } - public IList Fields { get; set; } = new List(); - public IList Methods { get; set; } = new List(); - } - - public virtual void Generate(GenerationParameters parameters) - { - FileUtil.RecreateDir(parameters.outputPath); - - for (int i = 0; i < parameters.classCount; i++) - { - Debug.Log($"[{GetType().Name}] Generating class {i}"); - var localRandom = new RandomWithKey(((RandomWithKey)parameters.random).Key, parameters.random.NextInt()); - string outputFile = $"{parameters.outputPath}/__GeneratedGarbageClass_{i}.cs"; - var result = new StringBuilder(64 * 1024); - GenerateClass(i, localRandom, result, parameters); - File.WriteAllText(outputFile, result.ToString(), Encoding.UTF8); - Debug.Log($"[{GetType().Name}] Generated class {i} to {outputFile}"); - } - } - - protected virtual void GenerateClass(int classIndex, IRandom random, StringBuilder result, GenerationParameters parameters) - { - IClassGenerationInfo cgi = CreateClassGenerationInfo(parameters.classNamespace, $"{parameters.classNamePrefix}{classIndex}", random, parameters); - result.AppendLine("using System;"); - result.AppendLine("using System.Collections.Generic;"); - result.AppendLine("using System.Linq;"); - result.AppendLine("using System.IO;"); - result.AppendLine("using UnityEngine;"); - - GenerateUsings(result, cgi); - - result.AppendLine($"namespace {cgi.Namespace}"); - result.AppendLine("{"); - result.AppendLine($" public class {cgi.Name}"); - result.AppendLine(" {"); - - string indent = " "; - foreach (object field in cgi.Fields) - { - GenerateField(result, cgi, field, indent); - } - foreach (object method in cgi.Methods) - { - GenerateMethod(result, cgi, method, indent); - } - result.AppendLine(" }"); - result.AppendLine("}"); - } - - protected abstract IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters); - - protected abstract void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi); - - protected abstract void GenerateField(StringBuilder result, IClassGenerationInfo cgi, object field, string indent); - - protected abstract void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, object method, string indent); - } public class ConfigGarbageCodeGenerator : SpecificGarbageCodeGeneratorBase { - class FieldGenerationInfo - { - public int index; - public string name; - public string type; - } - - class MethodGenerationInfo - { - public int index; - public string name; - } - - - protected override IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters) - { - var cgi = new ClassGenerationInfo - { - Namespace = classNamespace, - Name = className, - }; - - for (int i = 0; i < parameters.fieldCountPerClass; i++) - { - var fieldInfo = new FieldGenerationInfo - { - index = i, - name = $"x{i}", - type = CreateRandomType(random), - }; - cgi.Fields.Add(fieldInfo); - } - - for (int i = 0; i < parameters.methodCountPerClass; i++) - { - var methodInfo = new MethodGenerationInfo - { - index = i, - name = $"Load{i}", - }; - cgi.Methods.Add(methodInfo); - } - - return cgi; - } private readonly string[] _types = new string[] { @@ -150,17 +29,6 @@ namespace Obfuz.GarbageCodeGeneration return _types[random.NextInt(_types.Length)]; } - - protected override void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi) - { - } - - protected override void GenerateField(StringBuilder result, IClassGenerationInfo cgi, object field, string indent) - { - var fgi = (FieldGenerationInfo)field; - result.AppendLine($"{indent}public {fgi.type} {fgi.name};"); - } - private string GetReadMethodNameOfType(string type) { switch (type) @@ -175,16 +43,76 @@ namespace Obfuz.GarbageCodeGeneration default: throw new ArgumentException($"Unsupported type: {type}"); } } - - protected override void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, object method, string indent) + class FieldGenerationInfo { - result.AppendLine($"{indent}void Load(BinaryReader reader)"); + public int index; + public string name; + public string type; + } + + class MethodGenerationInfo + { + public int index; + public string name; + } + + protected override object CreateField(int index, IRandom random, GenerationParameters parameters) + { + return new FieldGenerationInfo + { + index = index, + name = $"x{index}", + type = CreateRandomType(random), + }; + } + + protected override object CreateMethod(int index, IRandom random, GenerationParameters parameters) + { + return new MethodGenerationInfo + { + index = index, + name = $"Load{index}", + }; + } + + protected override void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi) + { + } + + protected override void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent) + { + var fgi = (FieldGenerationInfo)field; + result.AppendLine($"{indent}public {fgi.type} {fgi.name};"); + } + + protected override void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent) + { + var mgi = (MethodGenerationInfo)method; + result.AppendLine($"{indent}public void {mgi.name}(BinaryReader reader)"); result.AppendLine($"{indent}{{"); string indent2 = indent + " "; - foreach (FieldGenerationInfo fgi in cgi.Fields) + result.AppendLine($"{indent2}int a = 0;"); + result.AppendLine($"{indent2}int b = 0;"); + int maxN = 100; + var shuffledFields = cgi.Fields.ToList(); + RandomUtil.ShuffleList(shuffledFields, random); + foreach (FieldGenerationInfo fgi in shuffledFields) { result.AppendLine($"{indent2}this.{fgi.name} = reader.{GetReadMethodNameOfType(fgi.type)}();"); + if (random.NextInPercentage(0.5f)) + { + result.AppendLine($"{indent2}a = b * {random.NextInt(maxN)} + reader.ReadInt32();"); + result.AppendLine($"{indent2}b = a * reader.ReadInt32() + {random.NextInt(maxN)};"); + } + if (random.NextInPercentage(0.5f)) + { + result.AppendLine($"{indent2}a += {random.NextInt(0, 10000)};"); + } + if (random.NextInPercentage(0.5f)) + { + result.AppendLine($"{indent2}b += {random.NextInt(0, 10000)};"); + } } result.AppendLine($"{indent}}}"); diff --git a/Editor/GarbageCodeGeneration/GarbageCodeGenerator.cs b/Editor/GarbageCodeGeneration/GarbageCodeGenerator.cs index de1944f..65d5bef 100644 --- a/Editor/GarbageCodeGeneration/GarbageCodeGenerator.cs +++ b/Editor/GarbageCodeGeneration/GarbageCodeGenerator.cs @@ -37,6 +37,22 @@ namespace Obfuz.GarbageCodeGeneration } } + public void CleanCodes() + { + Debug.Log($"Cleaning generated garbage codes begin."); + if (_settings.defaultTask != null) + { + FileUtil.RemoveDir(_settings.defaultTask.outputPath, true); + } + if (_settings.additionalTasks != null && _settings.additionalTasks.Length > 0) + { + foreach (var task in _settings.additionalTasks) + { + FileUtil.RemoveDir(task.outputPath, true); + } + } + } + private void GenerateTask(GarbageCodeGenerationTask task) { Debug.Log($"Generating garbage code with seed: {task.codeGenerationRandomSeed}, class count: {task.classCount}, method count per class: {task.methodCountPerClass}, types: {task.garbageCodeTypes}, output path: {task.outputPath}"); diff --git a/Editor/GarbageCodeGeneration/SpecificGarbageCodeGeneratorBase.cs b/Editor/GarbageCodeGeneration/SpecificGarbageCodeGeneratorBase.cs new file mode 100644 index 0000000..c237343 --- /dev/null +++ b/Editor/GarbageCodeGeneration/SpecificGarbageCodeGeneratorBase.cs @@ -0,0 +1,106 @@ +using Obfuz.Utils; +using System.Collections.Generic; +using System.IO; +using System.Text; +using UnityEngine; + +namespace Obfuz.GarbageCodeGeneration +{ + public abstract class SpecificGarbageCodeGeneratorBase : ISpecificGarbageCodeGenerator + { + protected interface IClassGenerationInfo + { + string Namespace { get; set; } + + string Name { get; set; } + + IList Fields { get; set; } + + IList Methods { get; set; } + } + + protected class ClassGenerationInfo : IClassGenerationInfo + { + public string Namespace { get; set; } + public string Name { get; set; } + public IList Fields { get; set; } = new List(); + public IList Methods { get; set; } = new List(); + } + + public virtual void Generate(GenerationParameters parameters) + { + FileUtil.RecreateDir(parameters.outputPath); + + for (int i = 0; i < parameters.classCount; i++) + { + Debug.Log($"[{GetType().Name}] Generating class {i}"); + var localRandom = new RandomWithKey(((RandomWithKey)parameters.random).Key, parameters.random.NextInt()); + string outputFile = $"{parameters.outputPath}/__GeneratedGarbageClass_{i}.cs"; + var result = new StringBuilder(64 * 1024); + GenerateClass(i, localRandom, result, parameters); + File.WriteAllText(outputFile, result.ToString(), Encoding.UTF8); + Debug.Log($"[{GetType().Name}] Generated class {i} to {outputFile}"); + } + } + + protected abstract object CreateField(int index, IRandom random, GenerationParameters parameters); + + protected abstract object CreateMethod(int index, IRandom random, GenerationParameters parameters); + + protected virtual IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters) + { + var cgi = new ClassGenerationInfo + { + Namespace = classNamespace, + Name = className, + }; + + for (int i = 0; i < parameters.fieldCountPerClass; i++) + { + cgi.Fields.Add(CreateField(i, random, parameters)); + } + + for (int i = 0; i < parameters.methodCountPerClass; i++) + { + cgi.Methods.Add(CreateMethod(i, random, parameters)); + } + + return cgi; + } + + protected virtual void GenerateClass(int classIndex, IRandom random, StringBuilder result, GenerationParameters parameters) + { + IClassGenerationInfo cgi = CreateClassGenerationInfo(parameters.classNamespace, $"{parameters.classNamePrefix}{classIndex}", random, parameters); + result.AppendLine("using System;"); + result.AppendLine("using System.Collections.Generic;"); + result.AppendLine("using System.Linq;"); + result.AppendLine("using System.IO;"); + result.AppendLine("using UnityEngine;"); + + GenerateUsings(result, cgi); + + result.AppendLine($"namespace {cgi.Namespace}"); + result.AppendLine("{"); + result.AppendLine($" public class {cgi.Name}"); + result.AppendLine(" {"); + + string indent = " "; + foreach (object field in cgi.Fields) + { + GenerateField(result, cgi, random, field, indent); + } + foreach (object method in cgi.Methods) + { + GenerateMethod(result, cgi, random, method, indent); + } + result.AppendLine(" }"); + result.AppendLine("}"); + } + + protected abstract void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi); + + protected abstract void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent); + + protected abstract void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent); + } +} diff --git a/Editor/GarbageCodeGeneration/SpecificGarbageCodeGeneratorBase.cs.meta b/Editor/GarbageCodeGeneration/SpecificGarbageCodeGeneratorBase.cs.meta new file mode 100644 index 0000000..7696864 --- /dev/null +++ b/Editor/GarbageCodeGeneration/SpecificGarbageCodeGeneratorBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bae18fd49482f00439d37f28a6a78d9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Unity/ObfuzMenu.cs b/Editor/Unity/ObfuzMenu.cs index 17b32ea..2237ba1 100644 --- a/Editor/Unity/ObfuzMenu.cs +++ b/Editor/Unity/ObfuzMenu.cs @@ -21,6 +21,7 @@ namespace Obfuz.Unity EncryptionVMSettings settings = ObfuzSettings.Instance.encryptionVMSettings; var generator = new VirtualMachineCodeGenerator(settings.codeGenerationSecretKey, settings.encryptionOpCodeCount); generator.Generate(settings.codeOutputPath); + AssetDatabase.Refresh(); } [MenuItem("Obfuz/GenerateSecretKeyFile", priority = 63)] @@ -37,16 +38,28 @@ namespace Obfuz.Unity AssetDatabase.Refresh(); } - [MenuItem("Obfuz/GenerateGarbageCodes", priority = 100)] + [MenuItem("Obfuz/GarbageCode/GenerateCodes", priority = 100)] public static void GenerateGarbageCodes() { Debug.Log($"Generating garbage codes begin."); GarbageCodeGeneratorSettings settings = ObfuzSettings.Instance.garbageCodeGeneratorSettings; var generator = new GarbageCodeGenerator(settings); generator.Generate(); + AssetDatabase.Refresh(); Debug.Log($"Generating garbage codes end."); } + [MenuItem("Obfuz/GarbageCode/CleanGeneratedCodes", priority = 101)] + public static void CleanGeneratedGarbageCodes() + { + Debug.Log($"Clean generated garbage codes begin."); + GarbageCodeGeneratorSettings settings = ObfuzSettings.Instance.garbageCodeGeneratorSettings; + var generator = new GarbageCodeGenerator(settings); + generator.CleanCodes(); + AssetDatabase.Refresh(); + Debug.Log($"Clean generated garbage codes end."); + } + private static void SaveKey(byte[] secret, string secretOutputPath) { FileUtil.CreateParentDir(secretOutputPath);